mirror of
https://github.com/opensim/opensim.git
synced 2026-08-08 18:25:33 +08:00
Patch from Johan: LibSL updated to the latest revision (1568) and all packets are now
recycled to improve performance and memory usage.
This commit is contained in:
@@ -26,11 +26,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using libsecondlife;
|
||||
using libsecondlife.Packets;
|
||||
using OpenSim.Framework.Console;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
@@ -42,6 +40,7 @@ namespace OpenSim.Framework
|
||||
|
||||
public void ForEachClient(ForEachClientDelegate whatToDo)
|
||||
{
|
||||
|
||||
// Wasteful, I know
|
||||
IClientAPI[] LocalClients = new IClientAPI[0];
|
||||
lock (m_clients)
|
||||
@@ -56,11 +55,9 @@ namespace OpenSim.Framework
|
||||
{
|
||||
whatToDo(LocalClients[i]);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (System.Exception e)
|
||||
{
|
||||
MainLog.Instance.Warn("CLIENT",
|
||||
"Unable to do ForEachClient for one of the clients" + "\n Reason: " +
|
||||
e.ToString());
|
||||
OpenSim.Framework.Console.MainLog.Instance.Warn("CLIENT", "Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,19 +107,20 @@ namespace OpenSim.Framework
|
||||
IClientAPI client;
|
||||
try
|
||||
{
|
||||
|
||||
if (m_clients.TryGetValue(circuits[i], out client))
|
||||
{
|
||||
Remove(client.CircuitCode);
|
||||
client.Close(false);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (System.Exception e)
|
||||
{
|
||||
MainLog.Instance.Error("CLIENT",
|
||||
"Unable to shutdown circuit for: " + agentId.ToString() + "\n Reason: " +
|
||||
e.ToString());
|
||||
OpenSim.Framework.Console.MainLog.Instance.Error("CLIENT", "Unable to shutdown circuit for: " + agentId.ToString() + "\n Reason: " + e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private uint[] GetAllCircuits(LLUUID agentId)
|
||||
@@ -137,7 +135,7 @@ namespace OpenSim.Framework
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < LocalClients.Length; i++)
|
||||
for (int i = 0; i < LocalClients.Length; i++ )
|
||||
{
|
||||
if (LocalClients[i].AgentId == agentId)
|
||||
{
|
||||
@@ -150,7 +148,8 @@ namespace OpenSim.Framework
|
||||
|
||||
public void ViewerEffectHandler(IClientAPI sender, ViewerEffectPacket.EffectBlock[] effectBlock)
|
||||
{
|
||||
ViewerEffectPacket packet = new ViewerEffectPacket();
|
||||
ViewerEffectPacket packet = (ViewerEffectPacket) PacketPool.Instance.GetPacket(PacketType.ViewerEffect);
|
||||
// TODO: don't create new blocks if recycling an old packet
|
||||
packet.Effect = effectBlock;
|
||||
|
||||
// Wasteful, I know
|
||||
@@ -170,6 +169,7 @@ namespace OpenSim.Framework
|
||||
packet.AgentData.SessionID = LocalClients[i].SessionId;
|
||||
LocalClients[i].OutPacket(packet, ThrottleOutPacketType.Task);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,4 +178,4 @@ namespace OpenSim.Framework
|
||||
return m_clients.TryGetValue(circuitId, out user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
131
OpenSim/Framework/PacketPool.cs
Normal file
131
OpenSim/Framework/PacketPool.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using libsecondlife.Packets;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public sealed class PacketPool
|
||||
{
|
||||
// Set up a thread-safe singleton pattern
|
||||
static PacketPool()
|
||||
{
|
||||
}
|
||||
|
||||
private static readonly PacketPool instance = new PacketPool();
|
||||
|
||||
public static PacketPool Instance
|
||||
{
|
||||
get { return instance; }
|
||||
}
|
||||
|
||||
private Hashtable pool = new Hashtable();
|
||||
|
||||
public Packet GetPacket(PacketType type)
|
||||
{
|
||||
Packet packet = null;
|
||||
|
||||
lock (pool)
|
||||
{
|
||||
if (pool[type] == null || ((Stack) pool[type]).Count == 0)
|
||||
{
|
||||
// Creating a new packet if we cannot reuse an old package
|
||||
packet = Packet.BuildPacket(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Recycle old packages
|
||||
packet = (Packet) ((Stack) pool[type]).Pop();
|
||||
}
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private byte[] decoded_header = new byte[10];
|
||||
private PacketType GetType(byte[] bytes)
|
||||
{
|
||||
ushort id;
|
||||
libsecondlife.PacketFrequency freq;
|
||||
|
||||
Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10);
|
||||
|
||||
if((bytes[0] & libsecondlife.Helpers.MSG_ZEROCODED)!=0)
|
||||
{
|
||||
libsecondlife.Helpers.ZeroDecodeCommand(bytes, decoded_header);
|
||||
}
|
||||
|
||||
if (decoded_header[6] == 0xFF)
|
||||
{
|
||||
if (decoded_header[7] == 0xFF)
|
||||
{
|
||||
id = (ushort)((decoded_header[8] << 8) + decoded_header[9]);
|
||||
freq = libsecondlife.PacketFrequency.Low;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (ushort)decoded_header[7];
|
||||
freq = libsecondlife.PacketFrequency.Medium;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (ushort)decoded_header[6];
|
||||
freq = libsecondlife.PacketFrequency.High;
|
||||
}
|
||||
|
||||
return Packet.GetType(id, freq);
|
||||
}
|
||||
|
||||
public Packet GetPacket(byte[] bytes, ref int packetEnd, byte[] zeroBuffer)
|
||||
{
|
||||
PacketType type = GetType(bytes);
|
||||
|
||||
int i = 0;
|
||||
Packet packet = GetPacket(type);
|
||||
packet.FromBytes(bytes, ref i, ref packetEnd, zeroBuffer);
|
||||
return packet;
|
||||
}
|
||||
|
||||
public void ReturnPacket(Packet packet)
|
||||
{
|
||||
lock (pool)
|
||||
{
|
||||
PacketType type = packet.Type;
|
||||
|
||||
if (pool[type] == null)
|
||||
{
|
||||
pool[type] = new Stack();
|
||||
}
|
||||
|
||||
((Stack) pool[type]).Push(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user