* Turned all instances of ForEach loops in ClientManager into Local Arrays.

* Added Locking while the Copy is taking place.
* Added an error message to describe what's actually happening.
afrisby
Teravus Ovares 2007-12-17 20:24:49 +00:00
parent f9540e3f11
commit adf7afb606
3 changed files with 65 additions and 19 deletions

View File

@ -40,9 +40,25 @@ namespace OpenSim.Framework
public void ForEachClient(ForEachClientDelegate whatToDo) public void ForEachClient(ForEachClientDelegate whatToDo)
{ {
foreach (IClientAPI client in m_clients.Values)
// Wasteful, I know
IClientAPI[] LocalClients = new IClientAPI[0];
lock (m_clients)
{ {
whatToDo(client); LocalClients = new IClientAPI[m_clients.Count];
m_clients.Values.CopyTo(LocalClients, 0);
}
for (int i = 0; i < LocalClients.Length; i++)
{
try
{
whatToDo(LocalClients[i]);
}
catch (System.Exception e)
{
OpenSim.Framework.Console.MainLog.Instance.Warn("CLIENT", "Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString());
}
} }
} }
@ -84,29 +100,48 @@ namespace OpenSim.Framework
public void CloseAllCircuits(LLUUID agentId) public void CloseAllCircuits(LLUUID agentId)
{ {
uint[] circuits = GetAllCircuits(agentId); uint[] circuits = GetAllCircuits(agentId);
foreach (uint circuit in circuits) // We're using a for loop here so changes to the circuits don't cause it to completely fail.
for (int i = 0; i < circuits.Length; i++)
{ {
IClientAPI client; IClientAPI client;
if (m_clients.TryGetValue(circuit, out client)) try
{ {
Remove(circuit);
client.Close(); if (m_clients.TryGetValue(circuits[i], out client))
{
Remove(client.CircuitCode);
client.Close();
}
}
catch (System.Exception e)
{
OpenSim.Framework.Console.MainLog.Instance.Error("CLIENT", "Unable to shutdown circuit for: " + agentId.ToString() + "\n Reason: " + e.ToString());
} }
} }
} }
private uint[] GetAllCircuits(LLUUID agentId) private uint[] GetAllCircuits(LLUUID agentId)
{ {
List<uint> circuits = new List<uint>(); List<uint> circuits = new List<uint>();
// Wasteful, I know
foreach (KeyValuePair<uint, IClientAPI> pair in m_clients) IClientAPI[] LocalClients = new IClientAPI[0];
lock (m_clients)
{ {
if (pair.Value.AgentId == agentId) LocalClients = new IClientAPI[m_clients.Count];
{ m_clients.Values.CopyTo(LocalClients, 0);
circuits.Add(pair.Key);
}
} }
for (int i = 0; i < LocalClients.Length; i++ )
{
if (LocalClients[i].AgentId == agentId)
{
circuits.Add(LocalClients[i].CircuitCode);
}
}
return circuits.ToArray(); return circuits.ToArray();
} }
@ -116,14 +151,24 @@ namespace OpenSim.Framework
ViewerEffectPacket packet = new ViewerEffectPacket(); ViewerEffectPacket packet = new ViewerEffectPacket();
packet.Effect = effectBlock; packet.Effect = effectBlock;
foreach (IClientAPI client in m_clients.Values) // Wasteful, I know
IClientAPI[] LocalClients = new IClientAPI[0];
lock (m_clients)
{ {
if (client.AgentId != sender.AgentId) LocalClients = new IClientAPI[m_clients.Count];
m_clients.Values.CopyTo(LocalClients, 0);
}
for (int i = 0; i < LocalClients.Length; i++)
{
if (LocalClients[i].AgentId != sender.AgentId)
{ {
packet.AgentData.AgentID = client.AgentId; packet.AgentData.AgentID = LocalClients[i].AgentId;
packet.AgentData.SessionID = client.SessionId; packet.AgentData.SessionID = LocalClients[i].SessionId;
client.OutPacket(packet,ThrottleOutPacketType.Task); LocalClients[i].OutPacket(packet, ThrottleOutPacketType.Task);
} }
} }
} }

View File

@ -209,8 +209,8 @@ namespace OpenSim.Region.ClientStack
m_scene.RemoveClient(AgentId); m_scene.RemoveClient(AgentId);
// Send the STOP packet // Send the STOP packet
libsecondlife.Packets.DisableSimulatorPacket disable = new libsecondlife.Packets.DisableSimulatorPacket(); //libsecondlife.Packets.DisableSimulatorPacket disable = new libsecondlife.Packets.DisableSimulatorPacket();
OutPacket(disable, ThrottleOutPacketType.Task); //OutPacket(disable, ThrottleOutPacketType.Task);
// FLUSH Packets // FLUSH Packets
m_packetQueue.Close(); m_packetQueue.Close();

View File

@ -459,6 +459,7 @@ namespace OpenSim.Region.Environment.Scenes
// This is the method that shuts down the scene. // This is the method that shuts down the scene.
public override void Close() public override void Close()
{ {
MainLog.Instance.Warn("SCENE", "Closing down the single simulator: " + RegionInfo.RegionName);
// Kick all ROOT agents with the message, 'The simulator is going down' // Kick all ROOT agents with the message, 'The simulator is going down'
ForEachScenePresence(delegate(ScenePresence avatar) ForEachScenePresence(delegate(ScenePresence avatar)
{ {