aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
authorKitto Flora2011-03-22 20:33:24 +0000
committerKitto Flora2011-03-22 20:33:24 +0000
commit764e8c2a4371c24d1a0bd067c0bcbc806562064d (patch)
tree03dfb1bfe16c420fdbb6a1aa723c9203771d1beb /OpenSim/Region/ClientStack
parentMerge branch 'careminster-presence-refactor' of ssh://3dhosting.de/var/git/ca... (diff)
parentAdd some more fields to Estate settings and make them work. (diff)
downloadopensim-SC_OLD-764e8c2a4371c24d1a0bd067c0bcbc806562064d.zip
opensim-SC_OLD-764e8c2a4371c24d1a0bd067c0bcbc806562064d.tar.gz
opensim-SC_OLD-764e8c2a4371c24d1a0bd067c0bcbc806562064d.tar.bz2
opensim-SC_OLD-764e8c2a4371c24d1a0bd067c0bcbc806562064d.tar.xz
Merge branch 'careminster-presence-refactor' of ssh://3dhosting.de/var/git/careminster into careminster-presence-refactor
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs16
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs171
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs26
3 files changed, 171 insertions, 42 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index f1fdbc5..d6159cd 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
@@ -257,9 +259,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 public string GetStats() 259 public string GetStats()
258 { 260 {
259 return string.Format( 261 return string.Format(
260 "{0,7} {1,7} {2,9} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7} {10,7}", 262 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}",
263 PacketsReceived,
261 PacketsSent, 264 PacketsSent,
262 PacketsReceived, 265 PacketsResent,
263 UnackedBytes, 266 UnackedBytes,
264 m_packetOutboxes[(int)ThrottleOutPacketType.Resend].Count, 267 m_packetOutboxes[(int)ThrottleOutPacketType.Resend].Count,
265 m_packetOutboxes[(int)ThrottleOutPacketType.Land].Count, 268 m_packetOutboxes[(int)ThrottleOutPacketType.Land].Count,
@@ -449,13 +452,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
449 /// an outgoing packet from each, obeying the throttling bucket limits 452 /// an outgoing packet from each, obeying the throttling bucket limits
450 /// </summary> 453 /// </summary>
451 /// 454 ///
455 /// <remarks>
452 /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower 456 /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower
453 /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have 457 /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have
454 /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the 458 /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the
455 /// wind queue). 459 /// wind queue).
456 /// 460 ///
457 /// <remarks>This function is only called from a synchronous loop in the 461 /// This function is only called from a synchronous loop in the
458 /// UDPServer so we don't need to bother making this thread safe</remarks> 462 /// UDPServer so we don't need to bother making this thread safe
463 /// </remarks>
464 ///
459 /// <returns>True if any packets were sent, otherwise false</returns> 465 /// <returns>True if any packets were sent, otherwise false</returns>
460 public bool DequeueOutgoing() 466 public bool DequeueOutgoing()
461 { 467 {
@@ -486,7 +492,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
486 m_udpServer.SendPacketFinal(nextPacket); 492 m_udpServer.SendPacketFinal(nextPacket);
487 m_nextPackets[i] = null; 493 m_nextPackets[i] = null;
488 packetSent = true; 494 packetSent = true;
489 this.PacketsSent++;
490 } 495 }
491 } 496 }
492 else 497 else
@@ -503,7 +508,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
503 // Send the packet 508 // Send the packet
504 m_udpServer.SendPacketFinal(packet); 509 m_udpServer.SendPacketFinal(packet);
505 packetSent = true; 510 packetSent = true;
506 this.PacketsSent++;
507 } 511 }
508 else 512 else
509 { 513 {
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 703176c..c865c0f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.IO; 31using System.IO;
31using System.Net; 32using System.Net;
32using System.Net.Sockets; 33using 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 }
@@ -844,7 +845,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
844 845
845 private void HandleUseCircuitCode(object o) 846 private void HandleUseCircuitCode(object o)
846 { 847 {
847 DateTime startTime = DateTime.Now; 848// DateTime startTime = DateTime.Now;
848 object[] array = (object[])o; 849 object[] array = (object[])o;
849 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; 850 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
850 UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1]; 851 UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1];
@@ -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
@@ -1052,6 +1060,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1052 1060
1053 #endregion Update Timers 1061 #endregion Update Timers
1054 1062
1063 // Use this for emergency monitoring -- bug hunting
1064 //if (m_scene.EmergencyMonitoring)
1065 // clientPacketHandler = MonitoredClientOutgoingPacketHandler;
1066 //else
1067 // clientPacketHandler = ClientOutgoingPacketHandler;
1068
1055 // Handle outgoing packets, resends, acknowledgements, and pings for each 1069 // Handle outgoing packets, resends, acknowledgements, and pings for each
1056 // 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
1057 m_scene.ForEachClient(clientPacketHandler); 1071 m_scene.ForEachClient(clientPacketHandler);
@@ -1067,6 +1081,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1067 { 1081 {
1068 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);
1069 } 1083 }
1084
1070 } 1085 }
1071 1086
1072 Watchdog.RemoveThread(); 1087 Watchdog.RemoveThread();
@@ -1104,6 +1119,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1104 } 1119 }
1105 } 1120 }
1106 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
1107 private void ProcessInPacket(object state) 1228 private void ProcessInPacket(object state)
1108 { 1229 {
1109 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 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 }