* 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)
{
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)
{
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;
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)
{
List<uint> circuits = new List<uint>();
foreach (KeyValuePair<uint, IClientAPI> pair in m_clients)
// Wasteful, I know
IClientAPI[] LocalClients = new IClientAPI[0];
lock (m_clients)
{
if (pair.Value.AgentId == agentId)
{
circuits.Add(pair.Key);
}
LocalClients = new IClientAPI[m_clients.Count];
m_clients.Values.CopyTo(LocalClients, 0);
}
for (int i = 0; i < LocalClients.Length; i++ )
{
if (LocalClients[i].AgentId == agentId)
{
circuits.Add(LocalClients[i].CircuitCode);
}
}
return circuits.ToArray();
}
@ -116,14 +151,24 @@ namespace OpenSim.Framework
ViewerEffectPacket packet = new ViewerEffectPacket();
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.SessionID = client.SessionId;
client.OutPacket(packet,ThrottleOutPacketType.Task);
packet.AgentData.AgentID = LocalClients[i].AgentId;
packet.AgentData.SessionID = LocalClients[i].SessionId;
LocalClients[i].OutPacket(packet, ThrottleOutPacketType.Task);
}
}
}

View File

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

View File

@ -459,6 +459,7 @@ namespace OpenSim.Region.Environment.Scenes
// This is the method that shuts down the scene.
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'
ForEachScenePresence(delegate(ScenePresence avatar)
{