diff options
Diffstat (limited to 'OpenSim/Region/ClientStack')
4 files changed, 175 insertions, 41 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index d4c3307..65a8fe3 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | |||
@@ -122,6 +122,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
122 | public int PacketsReceived; | 122 | public int PacketsReceived; |
123 | /// <summary>Number of packets sent to this client</summary> | 123 | /// <summary>Number of packets sent to this client</summary> |
124 | public int PacketsSent; | 124 | public int PacketsSent; |
125 | /// <summary>Number of packets resent to this client</summary> | ||
126 | public int PacketsResent; | ||
125 | /// <summary>Total byte count of unacked packets sent to this client</summary> | 127 | /// <summary>Total byte count of unacked packets sent to this client</summary> |
126 | public int UnackedBytes; | 128 | public int UnackedBytes; |
127 | 129 | ||
@@ -256,9 +258,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
256 | public string GetStats() | 258 | public string GetStats() |
257 | { | 259 | { |
258 | return string.Format( | 260 | return string.Format( |
259 | "{0,7} {1,7} {2,9} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7} {10,7}", | 261 | "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}", |
262 | PacketsReceived, | ||
260 | PacketsSent, | 263 | PacketsSent, |
261 | PacketsReceived, | 264 | PacketsResent, |
262 | UnackedBytes, | 265 | UnackedBytes, |
263 | m_packetOutboxes[(int)ThrottleOutPacketType.Resend].Count, | 266 | m_packetOutboxes[(int)ThrottleOutPacketType.Resend].Count, |
264 | m_packetOutboxes[(int)ThrottleOutPacketType.Land].Count, | 267 | m_packetOutboxes[(int)ThrottleOutPacketType.Land].Count, |
@@ -441,13 +444,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
441 | /// an outgoing packet from each, obeying the throttling bucket limits | 444 | /// an outgoing packet from each, obeying the throttling bucket limits |
442 | /// </summary> | 445 | /// </summary> |
443 | /// | 446 | /// |
447 | /// <remarks> | ||
444 | /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower | 448 | /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower |
445 | /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have | 449 | /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have |
446 | /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the | 450 | /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the |
447 | /// wind queue). | 451 | /// wind queue). |
448 | /// | 452 | /// |
449 | /// <remarks>This function is only called from a synchronous loop in the | 453 | /// This function is only called from a synchronous loop in the |
450 | /// UDPServer so we don't need to bother making this thread safe</remarks> | 454 | /// UDPServer so we don't need to bother making this thread safe |
455 | /// </remarks> | ||
456 | /// | ||
451 | /// <returns>True if any packets were sent, otherwise false</returns> | 457 | /// <returns>True if any packets were sent, otherwise false</returns> |
452 | public bool DequeueOutgoing() | 458 | public bool DequeueOutgoing() |
453 | { | 459 | { |
@@ -476,7 +482,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
476 | m_udpServer.SendPacketFinal(nextPacket); | 482 | m_udpServer.SendPacketFinal(nextPacket); |
477 | m_nextPackets[i] = null; | 483 | m_nextPackets[i] = null; |
478 | packetSent = true; | 484 | packetSent = true; |
479 | this.PacketsSent++; | ||
480 | } | 485 | } |
481 | } | 486 | } |
482 | else | 487 | else |
@@ -493,7 +498,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
493 | // Send the packet | 498 | // Send the packet |
494 | m_udpServer.SendPacketFinal(packet); | 499 | m_udpServer.SendPacketFinal(packet); |
495 | packetSent = true; | 500 | packetSent = true; |
496 | this.PacketsSent++; | ||
497 | } | 501 | } |
498 | else | 502 | else |
499 | { | 503 | { |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index df8ddbb..584c577 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | ||
30 | using System.IO; | 31 | using System.IO; |
31 | using System.Net; | 32 | using System.Net; |
32 | using System.Net.Sockets; | 33 | using System.Net.Sockets; |
@@ -506,7 +507,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
506 | 507 | ||
507 | // Bump up the resend count on this packet | 508 | // Bump up the resend count on this packet |
508 | Interlocked.Increment(ref outgoingPacket.ResendCount); | 509 | Interlocked.Increment(ref outgoingPacket.ResendCount); |
509 | //Interlocked.Increment(ref Stats.ResentPackets); | ||
510 | 510 | ||
511 | // Requeue or resend the packet | 511 | // Requeue or resend the packet |
512 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) | 512 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) |
@@ -582,6 +582,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
582 | udpClient.NeedAcks.Add(outgoingPacket); | 582 | udpClient.NeedAcks.Add(outgoingPacket); |
583 | } | 583 | } |
584 | } | 584 | } |
585 | else | ||
586 | { | ||
587 | Interlocked.Increment(ref udpClient.PacketsResent); | ||
588 | } | ||
585 | 589 | ||
586 | #endregion Sequence Number Assignment | 590 | #endregion Sequence Number Assignment |
587 | 591 | ||
@@ -636,10 +640,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
636 | { | 640 | { |
637 | object[] array = new object[] { buffer, packet }; | 641 | object[] array = new object[] { buffer, packet }; |
638 | 642 | ||
639 | if (m_asyncPacketHandling) | 643 | Util.FireAndForget(HandleUseCircuitCode, array); |
640 | Util.FireAndForget(HandleUseCircuitCode, array); | ||
641 | else | ||
642 | HandleUseCircuitCode(array); | ||
643 | 644 | ||
644 | return; | 645 | return; |
645 | } | 646 | } |
@@ -856,10 +857,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
856 | // Begin the process of adding the client to the simulator | 857 | // Begin the process of adding the client to the simulator |
857 | AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint); | 858 | AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint); |
858 | 859 | ||
859 | // Acknowledge the UseCircuitCode packet | 860 | // Send ack |
860 | SendAckImmediate(remoteEndPoint, packet.Header.Sequence); | 861 | SendAckImmediate(remoteEndPoint, packet.Header.Sequence); |
861 | 862 | ||
862 | // m_log.DebugFormat( | 863 | // m_log.DebugFormat( |
863 | // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", | 864 | // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", |
864 | // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); | 865 | // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); |
865 | } | 866 | } |
@@ -923,25 +924,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
923 | 924 | ||
924 | protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) | 925 | protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) |
925 | { | 926 | { |
926 | // Create the LLUDPClient | 927 | // In priciple there shouldn't be more than one thread here, ever. |
927 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | 928 | // But in case that happens, we need to synchronize this piece of code |
928 | IClientAPI existingClient; | 929 | // because it's too important |
929 | 930 | lock (this) | |
930 | if (!m_scene.TryGetClient(agentID, out existingClient)) | ||
931 | { | 931 | { |
932 | // Create the LLClientView | 932 | IClientAPI existingClient; |
933 | LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | ||
934 | client.OnLogout += LogoutHandler; | ||
935 | 933 | ||
936 | client.DisableFacelights = m_disableFacelights; | 934 | if (!m_scene.TryGetClient(agentID, out existingClient)) |
935 | { | ||
936 | // Create the LLUDPClient | ||
937 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | ||
938 | // Create the LLClientView | ||
939 | LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | ||
940 | client.OnLogout += LogoutHandler; | ||
937 | 941 | ||
938 | // Start the IClientAPI | 942 | client.DisableFacelights = m_disableFacelights; |
939 | client.Start(); | 943 | |
940 | } | 944 | // Start the IClientAPI |
941 | else | 945 | client.Start(); |
942 | { | 946 | |
943 | m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", | 947 | } |
944 | udpClient.AgentID, remoteEndPoint, circuitCode); | 948 | else |
949 | { | ||
950 | m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", | ||
951 | existingClient.AgentId, remoteEndPoint, circuitCode); | ||
952 | } | ||
945 | } | 953 | } |
946 | } | 954 | } |
947 | 955 | ||
@@ -1050,6 +1058,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1050 | 1058 | ||
1051 | #endregion Update Timers | 1059 | #endregion Update Timers |
1052 | 1060 | ||
1061 | // Use this for emergency monitoring -- bug hunting | ||
1062 | //if (m_scene.EmergencyMonitoring) | ||
1063 | // clientPacketHandler = MonitoredClientOutgoingPacketHandler; | ||
1064 | //else | ||
1065 | // clientPacketHandler = ClientOutgoingPacketHandler; | ||
1066 | |||
1053 | // Handle outgoing packets, resends, acknowledgements, and pings for each | 1067 | // Handle outgoing packets, resends, acknowledgements, and pings for each |
1054 | // client. m_packetSent will be set to true if a packet is sent | 1068 | // client. m_packetSent will be set to true if a packet is sent |
1055 | m_scene.ForEachClient(clientPacketHandler); | 1069 | m_scene.ForEachClient(clientPacketHandler); |
@@ -1065,6 +1079,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1065 | { | 1079 | { |
1066 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); | 1080 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); |
1067 | } | 1081 | } |
1082 | |||
1068 | } | 1083 | } |
1069 | 1084 | ||
1070 | Watchdog.RemoveThread(); | 1085 | Watchdog.RemoveThread(); |
@@ -1102,6 +1117,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1102 | } | 1117 | } |
1103 | } | 1118 | } |
1104 | 1119 | ||
1120 | #region Emergency Monitoring | ||
1121 | // Alternative packet handler fuull of instrumentation | ||
1122 | // Handy for hunting bugs | ||
1123 | private Stopwatch watch1 = new Stopwatch(); | ||
1124 | private Stopwatch watch2 = new Stopwatch(); | ||
1125 | |||
1126 | private float avgProcessingTicks = 0; | ||
1127 | private float avgResendUnackedTicks = 0; | ||
1128 | private float avgSendAcksTicks = 0; | ||
1129 | private float avgSendPingTicks = 0; | ||
1130 | private float avgDequeueTicks = 0; | ||
1131 | private long nticks = 0; | ||
1132 | private long nticksUnack = 0; | ||
1133 | private long nticksAck = 0; | ||
1134 | private long nticksPing = 0; | ||
1135 | private int npacksSent = 0; | ||
1136 | private int npackNotSent = 0; | ||
1137 | |||
1138 | private void MonitoredClientOutgoingPacketHandler(IClientAPI client) | ||
1139 | { | ||
1140 | nticks++; | ||
1141 | watch1.Start(); | ||
1142 | try | ||
1143 | { | ||
1144 | if (client is LLClientView) | ||
1145 | { | ||
1146 | LLUDPClient udpClient = ((LLClientView)client).UDPClient; | ||
1147 | |||
1148 | if (udpClient.IsConnected) | ||
1149 | { | ||
1150 | if (m_resendUnacked) | ||
1151 | { | ||
1152 | nticksUnack++; | ||
1153 | watch2.Start(); | ||
1154 | |||
1155 | ResendUnacked(udpClient); | ||
1156 | |||
1157 | watch2.Stop(); | ||
1158 | avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); | ||
1159 | watch2.Reset(); | ||
1160 | } | ||
1161 | |||
1162 | if (m_sendAcks) | ||
1163 | { | ||
1164 | nticksAck++; | ||
1165 | watch2.Start(); | ||
1166 | |||
1167 | SendAcks(udpClient); | ||
1168 | |||
1169 | watch2.Stop(); | ||
1170 | avgSendAcksTicks = (nticksAck - 1) / (float)nticksAck * avgSendAcksTicks + (watch2.ElapsedTicks / (float)nticksAck); | ||
1171 | watch2.Reset(); | ||
1172 | } | ||
1173 | |||
1174 | if (m_sendPing) | ||
1175 | { | ||
1176 | nticksPing++; | ||
1177 | watch2.Start(); | ||
1178 | |||
1179 | SendPing(udpClient); | ||
1180 | |||
1181 | watch2.Stop(); | ||
1182 | avgSendPingTicks = (nticksPing - 1) / (float)nticksPing * avgSendPingTicks + (watch2.ElapsedTicks / (float)nticksPing); | ||
1183 | watch2.Reset(); | ||
1184 | } | ||
1185 | |||
1186 | watch2.Start(); | ||
1187 | // Dequeue any outgoing packets that are within the throttle limits | ||
1188 | if (udpClient.DequeueOutgoing()) | ||
1189 | { | ||
1190 | m_packetSent = true; | ||
1191 | npacksSent++; | ||
1192 | } | ||
1193 | else | ||
1194 | npackNotSent++; | ||
1195 | |||
1196 | watch2.Stop(); | ||
1197 | avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks); | ||
1198 | watch2.Reset(); | ||
1199 | |||
1200 | } | ||
1201 | else | ||
1202 | m_log.WarnFormat("[LLUDPSERVER]: Client is not connected"); | ||
1203 | } | ||
1204 | } | ||
1205 | catch (Exception ex) | ||
1206 | { | ||
1207 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + | ||
1208 | " threw an exception: " + ex.Message, ex); | ||
1209 | } | ||
1210 | watch1.Stop(); | ||
1211 | avgProcessingTicks = (nticks - 1) / (float)nticks * avgProcessingTicks + (watch1.ElapsedTicks / (float)nticks); | ||
1212 | watch1.Reset(); | ||
1213 | |||
1214 | // reuse this -- it's every ~100ms | ||
1215 | if (m_scene.EmergencyMonitoring && nticks % 100 == 0) | ||
1216 | { | ||
1217 | m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})", | ||
1218 | avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent); | ||
1219 | npackNotSent = npacksSent = 0; | ||
1220 | } | ||
1221 | |||
1222 | } | ||
1223 | |||
1224 | #endregion | ||
1225 | |||
1105 | private void ProcessInPacket(object state) | 1226 | private void ProcessInPacket(object state) |
1106 | { | 1227 | { |
1107 | IncomingPacket incomingPacket = (IncomingPacket)state; | 1228 | IncomingPacket incomingPacket = (IncomingPacket)state; |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs index bdbd284..0a8331f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs | |||
@@ -210,6 +210,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
210 | content = Math.Min(content + dripAmount, maxBurst); | 210 | content = Math.Min(content + dripAmount, maxBurst); |
211 | lastDrip = now; | 211 | lastDrip = now; |
212 | 212 | ||
213 | if (dripAmount < 0 || content < 0) | ||
214 | // sim has been idle for too long, integer has overflown | ||
215 | // previous calculation is meaningless, let's put it at correct max | ||
216 | content = maxBurst; | ||
217 | |||
213 | return true; | 218 | return true; |
214 | } | 219 | } |
215 | } | 220 | } |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index 9d40688..d195110 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | |||
@@ -143,7 +143,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
143 | // Process all the pending adds | 143 | // Process all the pending adds |
144 | OutgoingPacket pendingAdd; | 144 | OutgoingPacket pendingAdd; |
145 | while (m_pendingAdds.TryDequeue(out pendingAdd)) | 145 | while (m_pendingAdds.TryDequeue(out pendingAdd)) |
146 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; | 146 | if (pendingAdd != null) |
147 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; | ||
147 | 148 | ||
148 | // Process all the pending removes, including updating statistics and round-trip times | 149 | // Process all the pending removes, including updating statistics and round-trip times |
149 | PendingAck pendingRemove; | 150 | PendingAck pendingRemove; |
@@ -152,17 +153,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
152 | { | 153 | { |
153 | if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) | 154 | if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) |
154 | { | 155 | { |
155 | m_packets.Remove(pendingRemove.SequenceNumber); | 156 | if (ackedPacket != null) |
156 | |||
157 | // Update stats | ||
158 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); | ||
159 | |||
160 | if (!pendingRemove.FromResend) | ||
161 | { | 157 | { |
162 | // Calculate the round-trip time for this packet and its ACK | 158 | m_packets.Remove(pendingRemove.SequenceNumber); |
163 | int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; | 159 | |
164 | if (rtt > 0) | 160 | // Update stats |
165 | ackedPacket.Client.UpdateRoundTrip(rtt); | 161 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); |
162 | |||
163 | if (!pendingRemove.FromResend) | ||
164 | { | ||
165 | // Calculate the round-trip time for this packet and its ACK | ||
166 | int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; | ||
167 | if (rtt > 0) | ||
168 | ackedPacket.Client.UpdateRoundTrip(rtt); | ||
169 | } | ||
166 | } | 170 | } |
167 | } | 171 | } |
168 | } | 172 | } |