diff options
Merge branch 'master' into careminster-presence-refactor
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 164 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | 45 |
2 files changed, 158 insertions, 51 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index cfcc057..b7f9d87 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; |
@@ -639,10 +640,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
639 | { | 640 | { |
640 | object[] array = new object[] { buffer, packet }; | 641 | object[] array = new object[] { buffer, packet }; |
641 | 642 | ||
642 | if (m_asyncPacketHandling) | 643 | Util.FireAndForget(HandleUseCircuitCode, array); |
643 | Util.FireAndForget(HandleUseCircuitCode, array); | ||
644 | else | ||
645 | HandleUseCircuitCode(array); | ||
646 | 644 | ||
647 | return; | 645 | return; |
648 | } | 646 | } |
@@ -859,10 +857,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
859 | // Begin the process of adding the client to the simulator | 857 | // Begin the process of adding the client to the simulator |
860 | AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint); | 858 | AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint); |
861 | 859 | ||
862 | // Acknowledge the UseCircuitCode packet | 860 | // Send ack |
863 | SendAckImmediate(remoteEndPoint, packet.Header.Sequence); | 861 | SendAckImmediate(remoteEndPoint, packet.Header.Sequence); |
864 | 862 | ||
865 | // m_log.DebugFormat( | 863 | // m_log.DebugFormat( |
866 | // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", | 864 | // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", |
867 | // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); | 865 | // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); |
868 | } | 866 | } |
@@ -926,25 +924,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
926 | 924 | ||
927 | 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) |
928 | { | 926 | { |
929 | // Create the LLUDPClient | 927 | // In priciple there shouldn't be more than one thread here, ever. |
930 | 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 |
931 | IClientAPI existingClient; | 929 | // because it's too important |
932 | 930 | lock (this) | |
933 | if (!m_scene.TryGetClient(agentID, out existingClient)) | ||
934 | { | 931 | { |
935 | // Create the LLClientView | 932 | IClientAPI existingClient; |
936 | LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | ||
937 | client.OnLogout += LogoutHandler; | ||
938 | 933 | ||
939 | 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; | ||
940 | 941 | ||
941 | // Start the IClientAPI | 942 | client.DisableFacelights = m_disableFacelights; |
942 | client.Start(); | 943 | |
943 | } | 944 | // Start the IClientAPI |
944 | else | 945 | client.Start(); |
945 | { | 946 | |
946 | m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", | 947 | } |
947 | 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 | } | ||
948 | } | 953 | } |
949 | } | 954 | } |
950 | 955 | ||
@@ -1055,6 +1060,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1055 | 1060 | ||
1056 | #endregion Update Timers | 1061 | #endregion Update Timers |
1057 | 1062 | ||
1063 | // Use this for emergency monitoring -- bug hunting | ||
1064 | //if (m_scene.EmergencyMonitoring) | ||
1065 | // clientPacketHandler = MonitoredClientOutgoingPacketHandler; | ||
1066 | //else | ||
1067 | // clientPacketHandler = ClientOutgoingPacketHandler; | ||
1068 | |||
1058 | // Handle outgoing packets, resends, acknowledgements, and pings for each | 1069 | // Handle outgoing packets, resends, acknowledgements, and pings for each |
1059 | // client. m_packetSent will be set to true if a packet is sent | 1070 | // client. m_packetSent will be set to true if a packet is sent |
1060 | m_scene.ForEachClient(clientPacketHandler); | 1071 | m_scene.ForEachClient(clientPacketHandler); |
@@ -1070,6 +1081,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1070 | { | 1081 | { |
1071 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); | 1082 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); |
1072 | } | 1083 | } |
1084 | |||
1073 | } | 1085 | } |
1074 | 1086 | ||
1075 | Watchdog.RemoveThread(); | 1087 | Watchdog.RemoveThread(); |
@@ -1107,6 +1119,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1107 | } | 1119 | } |
1108 | } | 1120 | } |
1109 | 1121 | ||
1122 | #region Emergency Monitoring | ||
1123 | // Alternative packet handler fuull of instrumentation | ||
1124 | // Handy for hunting bugs | ||
1125 | private Stopwatch watch1 = new Stopwatch(); | ||
1126 | private Stopwatch watch2 = new Stopwatch(); | ||
1127 | |||
1128 | private float avgProcessingTicks = 0; | ||
1129 | private float avgResendUnackedTicks = 0; | ||
1130 | private float avgSendAcksTicks = 0; | ||
1131 | private float avgSendPingTicks = 0; | ||
1132 | private float avgDequeueTicks = 0; | ||
1133 | private long nticks = 0; | ||
1134 | private long nticksUnack = 0; | ||
1135 | private long nticksAck = 0; | ||
1136 | private long nticksPing = 0; | ||
1137 | private int npacksSent = 0; | ||
1138 | private int npackNotSent = 0; | ||
1139 | |||
1140 | private void MonitoredClientOutgoingPacketHandler(IClientAPI client) | ||
1141 | { | ||
1142 | nticks++; | ||
1143 | watch1.Start(); | ||
1144 | try | ||
1145 | { | ||
1146 | if (client is LLClientView) | ||
1147 | { | ||
1148 | LLUDPClient udpClient = ((LLClientView)client).UDPClient; | ||
1149 | |||
1150 | if (udpClient.IsConnected) | ||
1151 | { | ||
1152 | if (m_resendUnacked) | ||
1153 | { | ||
1154 | nticksUnack++; | ||
1155 | watch2.Start(); | ||
1156 | |||
1157 | ResendUnacked(udpClient); | ||
1158 | |||
1159 | watch2.Stop(); | ||
1160 | avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); | ||
1161 | watch2.Reset(); | ||
1162 | } | ||
1163 | |||
1164 | if (m_sendAcks) | ||
1165 | { | ||
1166 | nticksAck++; | ||
1167 | watch2.Start(); | ||
1168 | |||
1169 | SendAcks(udpClient); | ||
1170 | |||
1171 | watch2.Stop(); | ||
1172 | avgSendAcksTicks = (nticksAck - 1) / (float)nticksAck * avgSendAcksTicks + (watch2.ElapsedTicks / (float)nticksAck); | ||
1173 | watch2.Reset(); | ||
1174 | } | ||
1175 | |||
1176 | if (m_sendPing) | ||
1177 | { | ||
1178 | nticksPing++; | ||
1179 | watch2.Start(); | ||
1180 | |||
1181 | SendPing(udpClient); | ||
1182 | |||
1183 | watch2.Stop(); | ||
1184 | avgSendPingTicks = (nticksPing - 1) / (float)nticksPing * avgSendPingTicks + (watch2.ElapsedTicks / (float)nticksPing); | ||
1185 | watch2.Reset(); | ||
1186 | } | ||
1187 | |||
1188 | watch2.Start(); | ||
1189 | // Dequeue any outgoing packets that are within the throttle limits | ||
1190 | if (udpClient.DequeueOutgoing()) | ||
1191 | { | ||
1192 | m_packetSent = true; | ||
1193 | npacksSent++; | ||
1194 | } | ||
1195 | else | ||
1196 | npackNotSent++; | ||
1197 | |||
1198 | watch2.Stop(); | ||
1199 | avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks); | ||
1200 | watch2.Reset(); | ||
1201 | |||
1202 | } | ||
1203 | else | ||
1204 | m_log.WarnFormat("[LLUDPSERVER]: Client is not connected"); | ||
1205 | } | ||
1206 | } | ||
1207 | catch (Exception ex) | ||
1208 | { | ||
1209 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + | ||
1210 | " threw an exception: " + ex.Message, ex); | ||
1211 | } | ||
1212 | watch1.Stop(); | ||
1213 | avgProcessingTicks = (nticks - 1) / (float)nticks * avgProcessingTicks + (watch1.ElapsedTicks / (float)nticks); | ||
1214 | watch1.Reset(); | ||
1215 | |||
1216 | // reuse this -- it's every ~100ms | ||
1217 | if (m_scene.EmergencyMonitoring && nticks % 100 == 0) | ||
1218 | { | ||
1219 | 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})", | ||
1220 | avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent); | ||
1221 | npackNotSent = npacksSent = 0; | ||
1222 | } | ||
1223 | |||
1224 | } | ||
1225 | |||
1226 | #endregion | ||
1227 | |||
1110 | private void ProcessInPacket(object state) | 1228 | private void ProcessInPacket(object state) |
1111 | { | 1229 | { |
1112 | IncomingPacket incomingPacket = (IncomingPacket)state; | 1230 | IncomingPacket incomingPacket = (IncomingPacket)state; |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index d762bef..d195110 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | |||
@@ -141,46 +141,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
141 | private void ProcessQueues() | 141 | private void ProcessQueues() |
142 | { | 142 | { |
143 | // Process all the pending adds | 143 | // Process all the pending adds |
144 | |||
145 | OutgoingPacket pendingAdd; | 144 | OutgoingPacket pendingAdd; |
146 | if (m_pendingAdds != null) | 145 | while (m_pendingAdds.TryDequeue(out pendingAdd)) |
147 | { | 146 | if (pendingAdd != null) |
148 | while (m_pendingAdds.TryDequeue(out pendingAdd)) | 147 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; |
149 | { | ||
150 | if (pendingAdd != null && m_packets != null) | ||
151 | { | ||
152 | m_packets[pendingAdd.SequenceNumber] = pendingAdd; | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | 148 | ||
157 | // 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 |
158 | PendingAck pendingRemove; | 150 | PendingAck pendingRemove; |
159 | OutgoingPacket ackedPacket; | 151 | OutgoingPacket ackedPacket; |
160 | if (m_pendingRemoves != null) | 152 | while (m_pendingRemoves.TryDequeue(out pendingRemove)) |
161 | { | 153 | { |
162 | while (m_pendingRemoves.TryDequeue(out pendingRemove)) | 154 | if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) |
163 | { | 155 | { |
164 | if (m_pendingRemoves != null && m_packets != null) | 156 | if (ackedPacket != null) |
165 | { | 157 | { |
166 | if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) | 158 | m_packets.Remove(pendingRemove.SequenceNumber); |
159 | |||
160 | // Update stats | ||
161 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); | ||
162 | |||
163 | if (!pendingRemove.FromResend) | ||
167 | { | 164 | { |
168 | m_packets.Remove(pendingRemove.SequenceNumber); | 165 | // Calculate the round-trip time for this packet and its ACK |
169 | 166 | int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; | |
170 | // Update stats | 167 | if (rtt > 0) |
171 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); | 168 | ackedPacket.Client.UpdateRoundTrip(rtt); |
172 | |||
173 | if (!pendingRemove.FromResend) | ||
174 | { | ||
175 | // Calculate the round-trip time for this packet and its ACK | ||
176 | int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; | ||
177 | if (rtt > 0) | ||
178 | ackedPacket.Client.UpdateRoundTrip(rtt); | ||
179 | } | ||
180 | } | 169 | } |
181 | } | 170 | } |
182 | } | 171 | } |
183 | } | 172 | } |
184 | } | 173 | } |
185 | } | 174 | } |
186 | } | 175 | } \ No newline at end of file |