diff options
author | John Hurliman | 2009-10-06 10:12:59 -0700 |
---|---|---|
committer | John Hurliman | 2009-10-06 10:12:59 -0700 |
commit | fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98 (patch) | |
tree | bef6315759b63e337e17d7d1e717929e08778f8c | |
parent | Fixing a few compile errors in the previous commit (diff) | |
download | opensim-SC-fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98.zip opensim-SC-fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98.tar.gz opensim-SC-fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98.tar.bz2 opensim-SC-fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98.tar.xz |
* Try/catch around EndInvoke() when Util.FireAndForget() returns to catch exceptions thrown in the async method
* Added packet stats handling to the new LLUDP implementation
* Attempting to avoid a race condition when creating a new LLUDPClient
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/Util.cs | 4 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 3 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | 40 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 147 |
4 files changed, 115 insertions, 79 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 189fa38..38729c6 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -1283,7 +1283,9 @@ namespace OpenSim.Framework | |||
1283 | { | 1283 | { |
1284 | System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; | 1284 | System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; |
1285 | 1285 | ||
1286 | callback.EndInvoke(ar); | 1286 | try { callback.EndInvoke(ar); } |
1287 | catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } | ||
1288 | |||
1287 | ar.AsyncWaitHandle.Close(); | 1289 | ar.AsyncWaitHandle.Close(); |
1288 | } | 1290 | } |
1289 | 1291 | ||
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 767020f..84e705a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -186,8 +186,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
186 | m_udpServer = udpServer; | 186 | m_udpServer = udpServer; |
187 | m_udpClient = udpClient; | 187 | m_udpClient = udpClient; |
188 | m_udpClient.OnQueueEmpty += HandleQueueEmpty; | 188 | m_udpClient.OnQueueEmpty += HandleQueueEmpty; |
189 | // FIXME: Implement this | 189 | m_udpClient.OnPacketStats += PopulateStats; |
190 | //m_udpClient.OnPacketStats += PopulateStats; | ||
191 | 190 | ||
192 | RegisterLocalPacketHandlers(); | 191 | RegisterLocalPacketHandlers(); |
193 | } | 192 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index ad01135..f2e76d3 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | |||
@@ -33,6 +33,7 @@ using OpenMetaverse; | |||
33 | 33 | ||
34 | namespace OpenSim.Region.ClientStack.LindenUDP | 34 | namespace OpenSim.Region.ClientStack.LindenUDP |
35 | { | 35 | { |
36 | public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); | ||
36 | public delegate void QueueEmpty(ThrottleOutPacketType category); | 37 | public delegate void QueueEmpty(ThrottleOutPacketType category); |
37 | 38 | ||
38 | public class LLUDPClient | 39 | public class LLUDPClient |
@@ -41,6 +42,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
41 | /// or removed, this number must also change</summary> | 42 | /// or removed, this number must also change</summary> |
42 | const int THROTTLE_CATEGORY_COUNT = 7; | 43 | const int THROTTLE_CATEGORY_COUNT = 7; |
43 | 44 | ||
45 | public event PacketStats OnPacketStats; | ||
44 | public event QueueEmpty OnQueueEmpty; | 46 | public event QueueEmpty OnQueueEmpty; |
45 | 47 | ||
46 | /// <summary>AgentID for this client</summary> | 48 | /// <summary>AgentID for this client</summary> |
@@ -84,6 +86,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
84 | /// <summary>Number of bytes received since the last acknowledgement was sent out. This is used | 86 | /// <summary>Number of bytes received since the last acknowledgement was sent out. This is used |
85 | /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2)</summary> | 87 | /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2)</summary> |
86 | public int BytesSinceLastACK; | 88 | public int BytesSinceLastACK; |
89 | /// <summary>Number of packets received from this client</summary> | ||
90 | public int PacketsReceived; | ||
91 | /// <summary>Number of packets sent to this client</summary> | ||
92 | public int PacketsSent; | ||
93 | /// <summary>Total byte count of unacked packets sent to this client</summary> | ||
94 | public int UnackedBytes; | ||
95 | |||
96 | /// <summary>Total number of received packets that we have reported to the OnPacketStats event(s)</summary> | ||
97 | private int m_packetsReceivedReported; | ||
98 | /// <summary>Total number of sent packets that we have reported to the OnPacketStats event(s)</summary> | ||
99 | private int m_packetsSentReported; | ||
87 | 100 | ||
88 | /// <summary>Throttle bucket for this agent's connection</summary> | 101 | /// <summary>Throttle bucket for this agent's connection</summary> |
89 | private readonly TokenBucket throttle; | 102 | private readonly TokenBucket throttle; |
@@ -162,17 +175,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
162 | 175 | ||
163 | public string GetStats() | 176 | public string GetStats() |
164 | { | 177 | { |
178 | // TODO: ??? | ||
165 | return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", | 179 | return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", |
166 | 0, | 180 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); |
167 | 0, | 181 | } |
168 | 0, | 182 | |
169 | 0, | 183 | public void SendPacketStats() |
170 | 0, | 184 | { |
171 | 0, | 185 | PacketStats callback = OnPacketStats; |
172 | 0, | 186 | if (callback != null) |
173 | 0, | 187 | { |
174 | 0, | 188 | int newPacketsReceived = PacketsReceived - m_packetsReceivedReported; |
175 | 0); | 189 | int newPacketsSent = PacketsSent - m_packetsSentReported; |
190 | |||
191 | callback(newPacketsReceived, newPacketsSent, UnackedBytes); | ||
192 | |||
193 | m_packetsReceivedReported += newPacketsReceived; | ||
194 | m_packetsSentReported += newPacketsSent; | ||
195 | } | ||
176 | } | 196 | } |
177 | 197 | ||
178 | public void SetThrottles(byte[] throttleData) | 198 | public void SetThrottles(byte[] throttleData) |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 348615e..38890da 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -359,6 +359,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
359 | // is actually sent out again | 359 | // is actually sent out again |
360 | outgoingPacket.TickCount = 0; | 360 | outgoingPacket.TickCount = 0; |
361 | 361 | ||
362 | // Bump up the resend count on this packet | ||
362 | Interlocked.Increment(ref outgoingPacket.ResendCount); | 363 | Interlocked.Increment(ref outgoingPacket.ResendCount); |
363 | //Interlocked.Increment(ref Stats.ResentPackets); | 364 | //Interlocked.Increment(ref Stats.ResentPackets); |
364 | 365 | ||
@@ -393,6 +394,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
393 | 394 | ||
394 | public void Flush() | 395 | public void Flush() |
395 | { | 396 | { |
397 | // FIXME: Implement? | ||
398 | } | ||
399 | |||
400 | internal void SendPacketFinal(OutgoingPacket outgoingPacket) | ||
401 | { | ||
402 | UDPPacketBuffer buffer = outgoingPacket.Buffer; | ||
403 | byte flags = buffer.Data[0]; | ||
404 | bool isResend = (flags & Helpers.MSG_RESENT) != 0; | ||
405 | bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; | ||
406 | LLUDPClient client = outgoingPacket.Client; | ||
407 | |||
408 | // Keep track of when this packet was sent out (right now) | ||
409 | outgoingPacket.TickCount = Environment.TickCount; | ||
410 | |||
411 | #region ACK Appending | ||
412 | |||
413 | int dataLength = buffer.DataLength; | ||
414 | |||
415 | // Keep appending ACKs until there is no room left in the packet or there are | ||
416 | // no more ACKs to append | ||
417 | uint ackCount = 0; | ||
418 | uint ack; | ||
419 | while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) | ||
420 | { | ||
421 | Utils.UIntToBytesBig(ack, buffer.Data, dataLength); | ||
422 | dataLength += 4; | ||
423 | ++ackCount; | ||
424 | } | ||
425 | |||
426 | if (ackCount > 0) | ||
427 | { | ||
428 | // Set the last byte of the packet equal to the number of appended ACKs | ||
429 | buffer.Data[dataLength++] = (byte)ackCount; | ||
430 | // Set the appended ACKs flag on this packet | ||
431 | buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); | ||
432 | } | ||
433 | |||
434 | buffer.DataLength = dataLength; | ||
435 | |||
436 | #endregion ACK Appending | ||
437 | |||
438 | if (!isResend) | ||
439 | { | ||
440 | // Not a resend, assign a new sequence number | ||
441 | uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); | ||
442 | Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); | ||
443 | outgoingPacket.SequenceNumber = sequenceNumber; | ||
444 | |||
445 | if (isReliable) | ||
446 | { | ||
447 | // Add this packet to the list of ACK responses we are waiting on from the server | ||
448 | client.NeedAcks.Add(outgoingPacket); | ||
449 | } | ||
450 | } | ||
451 | |||
452 | // Stats tracking | ||
453 | Interlocked.Increment(ref client.PacketsSent); | ||
454 | if (isReliable) | ||
455 | Interlocked.Add(ref client.UnackedBytes, outgoingPacket.Buffer.DataLength); | ||
456 | |||
457 | // Put the UDP payload on the wire | ||
458 | AsyncBeginSend(buffer); | ||
396 | } | 459 | } |
397 | 460 | ||
398 | protected override void PacketReceived(UDPPacketBuffer buffer) | 461 | protected override void PacketReceived(UDPPacketBuffer buffer) |
@@ -456,8 +519,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
456 | 519 | ||
457 | #endregion UseCircuitCode Handling | 520 | #endregion UseCircuitCode Handling |
458 | 521 | ||
459 | //if (packet.Header.Resent) | 522 | // Stats tracking |
460 | // Interlocked.Increment(ref Stats.ReceivedResends); | 523 | Interlocked.Increment(ref client.PacketsReceived); |
461 | 524 | ||
462 | #region ACK Receiving | 525 | #region ACK Receiving |
463 | 526 | ||
@@ -581,7 +644,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
581 | { | 644 | { |
582 | // Create the LLUDPClient | 645 | // Create the LLUDPClient |
583 | LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); | 646 | LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); |
584 | clients.Add(agentID, client.RemoteEndPoint, client); | ||
585 | 647 | ||
586 | // Create the LLClientView | 648 | // Create the LLClientView |
587 | LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); | 649 | LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); |
@@ -589,12 +651,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
589 | clientApi.OnLogout += LogoutHandler; | 651 | clientApi.OnLogout += LogoutHandler; |
590 | clientApi.OnConnectionClosed += RemoveClient; | 652 | clientApi.OnConnectionClosed += RemoveClient; |
591 | 653 | ||
592 | // Give LLUDPClient a reference to IClientAPI | ||
593 | client.ClientAPI = clientApi; | ||
594 | |||
595 | // Start the IClientAPI | 654 | // Start the IClientAPI |
596 | m_scene.ClientManager.Add(circuitCode, clientApi); | 655 | m_scene.ClientManager.Add(circuitCode, clientApi); |
597 | clientApi.Start(); | 656 | clientApi.Start(); |
657 | |||
658 | // Give LLUDPClient a reference to IClientAPI | ||
659 | client.ClientAPI = clientApi; | ||
660 | |||
661 | // Add the new client to our list of tracked clients | ||
662 | clients.Add(agentID, client.RemoteEndPoint, client); | ||
598 | } | 663 | } |
599 | 664 | ||
600 | private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) | 665 | private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) |
@@ -602,6 +667,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
602 | OutgoingPacket ackedPacket; | 667 | OutgoingPacket ackedPacket; |
603 | if (client.NeedAcks.RemoveUnsafe(ack, out ackedPacket) && !fromResend) | 668 | if (client.NeedAcks.RemoveUnsafe(ack, out ackedPacket) && !fromResend) |
604 | { | 669 | { |
670 | // Update stats | ||
671 | Interlocked.Add(ref client.UnackedBytes, -ackedPacket.Buffer.DataLength); | ||
672 | |||
605 | // Calculate the round-trip time for this packet and its ACK | 673 | // Calculate the round-trip time for this packet and its ACK |
606 | int rtt = currentTime - ackedPacket.TickCount; | 674 | int rtt = currentTime - ackedPacket.TickCount; |
607 | if (rtt > 0) | 675 | if (rtt > 0) |
@@ -650,7 +718,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
650 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); | 718 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); |
651 | 719 | ||
652 | // Don't let a failure in an individual client thread crash the whole sim. | 720 | // Don't let a failure in an individual client thread crash the whole sim. |
653 | m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} {1} crashed. Logging them out", client.ClientAPI.Name, client.AgentID); | 721 | m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} crashed. Logging them out", client.AgentID); |
654 | m_log.Error(e.Message, e); | 722 | m_log.Error(e.Message, e); |
655 | 723 | ||
656 | try | 724 | try |
@@ -674,7 +742,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
674 | } | 742 | } |
675 | catch (Exception e2) | 743 | catch (Exception e2) |
676 | { | 744 | { |
677 | m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.ClientAPI.Name); | 745 | m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.AgentID); |
678 | m_log.Error(e2.Message, e2); | 746 | m_log.Error(e2.Message, e2); |
679 | } | 747 | } |
680 | } | 748 | } |
@@ -715,8 +783,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
715 | elapsed100MS = 0; | 783 | elapsed100MS = 0; |
716 | ++elapsed500MS; | 784 | ++elapsed500MS; |
717 | } | 785 | } |
718 | // Send pings to clients every 2000ms | 786 | // Send pings to clients every 5000ms |
719 | if (elapsed500MS >= 4) | 787 | if (elapsed500MS >= 10) |
720 | { | 788 | { |
721 | sendPings = true; | 789 | sendPings = true; |
722 | elapsed500MS = 0; | 790 | elapsed500MS = 0; |
@@ -730,7 +798,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
730 | if (resendUnacked) | 798 | if (resendUnacked) |
731 | ResendUnacked(client); | 799 | ResendUnacked(client); |
732 | if (sendAcks) | 800 | if (sendAcks) |
801 | { | ||
733 | SendAcks(client); | 802 | SendAcks(client); |
803 | client.SendPacketStats(); | ||
804 | } | ||
734 | if (sendPings) | 805 | if (sendPings) |
735 | SendPing(client); | 806 | SendPing(client); |
736 | } | 807 | } |
@@ -746,61 +817,5 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
746 | client.SendLogoutPacket(); | 817 | client.SendLogoutPacket(); |
747 | RemoveClient(client); | 818 | RemoveClient(client); |
748 | } | 819 | } |
749 | |||
750 | internal void SendPacketFinal(OutgoingPacket outgoingPacket) | ||
751 | { | ||
752 | UDPPacketBuffer buffer = outgoingPacket.Buffer; | ||
753 | byte flags = buffer.Data[0]; | ||
754 | bool isResend = (flags & Helpers.MSG_RESENT) != 0; | ||
755 | bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; | ||
756 | LLUDPClient client = outgoingPacket.Client; | ||
757 | |||
758 | // Keep track of when this packet was sent out (right now) | ||
759 | outgoingPacket.TickCount = Environment.TickCount; | ||
760 | |||
761 | #region ACK Appending | ||
762 | |||
763 | int dataLength = buffer.DataLength; | ||
764 | |||
765 | // Keep appending ACKs until there is no room left in the packet or there are | ||
766 | // no more ACKs to append | ||
767 | uint ackCount = 0; | ||
768 | uint ack; | ||
769 | while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) | ||
770 | { | ||
771 | Utils.UIntToBytesBig(ack, buffer.Data, dataLength); | ||
772 | dataLength += 4; | ||
773 | ++ackCount; | ||
774 | } | ||
775 | |||
776 | if (ackCount > 0) | ||
777 | { | ||
778 | // Set the last byte of the packet equal to the number of appended ACKs | ||
779 | buffer.Data[dataLength++] = (byte)ackCount; | ||
780 | // Set the appended ACKs flag on this packet | ||
781 | buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); | ||
782 | } | ||
783 | |||
784 | buffer.DataLength = dataLength; | ||
785 | |||
786 | #endregion ACK Appending | ||
787 | |||
788 | if (!isResend) | ||
789 | { | ||
790 | // Not a resend, assign a new sequence number | ||
791 | uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); | ||
792 | Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); | ||
793 | outgoingPacket.SequenceNumber = sequenceNumber; | ||
794 | |||
795 | if (isReliable) | ||
796 | { | ||
797 | // Add this packet to the list of ACK responses we are waiting on from the server | ||
798 | client.NeedAcks.Add(outgoingPacket); | ||
799 | } | ||
800 | } | ||
801 | |||
802 | // Put the UDP payload on the wire | ||
803 | AsyncBeginSend(buffer); | ||
804 | } | ||
805 | } | 820 | } |
806 | } | 821 | } |