From f0178a6a413e35a45efcb0f7f0eeffc0daed15fe Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 01:12:56 +0100 Subject: refactor: Move OpenSim.Framework.PacketPool to OpenSim.Region.Clientstack.Linden.UDP This is to allow it to use OpenSim.Framework.Monitoring in the future. This is also a better location since the packet pool is linden udp specific --- .../Region/ClientStack/Linden/UDP/PacketPool.cs | 249 +++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs new file mode 100644 index 0000000..fc9406b --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -0,0 +1,249 @@ +/* + * 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 OpenSimulator 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.Generic; +using System.Reflection; +using OpenMetaverse; +using OpenMetaverse.Packets; +using log4net; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public sealed class PacketPool + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly PacketPool instance = new PacketPool(); + + private bool packetPoolEnabled = true; + private bool dataBlockPoolEnabled = true; + + /// + /// Pool of packets available for reuse. + /// + private readonly Dictionary> pool = new Dictionary>(); + + private static Dictionary> DataBlocks = + new Dictionary>(); + + static PacketPool() + { + } + + public static PacketPool Instance + { + get { return instance; } + } + + public bool RecyclePackets + { + set { packetPoolEnabled = value; } + get { return packetPoolEnabled; } + } + + public bool RecycleDataBlocks + { + set { dataBlockPoolEnabled = value; } + get { return dataBlockPoolEnabled; } + } + + public Packet GetPacket(PacketType type) + { + Packet packet; + + if (!packetPoolEnabled) + return Packet.BuildPacket(type); + + lock (pool) + { + if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) + { + // Creating a new packet if we cannot reuse an old package + packet = Packet.BuildPacket(type); + } + else + { + // Recycle old packages + packet = (pool[type]).Pop(); + } + } + + return packet; + } + + // private byte[] decoded_header = new byte[10]; + private static PacketType GetType(byte[] bytes) + { + byte[] decoded_header = new byte[10 + 8]; + ushort id; + PacketFrequency freq; + + if ((bytes[0] & Helpers.MSG_ZEROCODED) != 0) + { + Helpers.ZeroDecode(bytes, 16, decoded_header); + } + else + { + Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10); + } + + if (decoded_header[6] == 0xFF) + { + if (decoded_header[7] == 0xFF) + { + id = (ushort) ((decoded_header[8] << 8) + decoded_header[9]); + freq = PacketFrequency.Low; + } + else + { + id = decoded_header[7]; + freq = PacketFrequency.Medium; + } + } + else + { + id = decoded_header[6]; + freq = PacketFrequency.High; + } + + return Packet.GetType(id, freq); + } + + public Packet GetPacket(byte[] bytes, ref int packetEnd, byte[] zeroBuffer) + { + PacketType type = GetType(bytes); + + Array.Clear(zeroBuffer, 0, zeroBuffer.Length); + + int i = 0; + Packet packet = GetPacket(type); + if (packet == null) + m_log.WarnFormat("[PACKETPOOL]: Failed to get packet of type {0}", type); + else + packet.FromBytes(bytes, ref i, ref packetEnd, zeroBuffer); + + return packet; + } + + /// + /// Return a packet to the packet pool + /// + /// + public void ReturnPacket(Packet packet) + { + if (dataBlockPoolEnabled) + { + switch (packet.Type) + { + case PacketType.ObjectUpdate: + ObjectUpdatePacket oup = (ObjectUpdatePacket)packet; + + foreach (ObjectUpdatePacket.ObjectDataBlock oupod in oup.ObjectData) + ReturnDataBlock(oupod); + + oup.ObjectData = null; + break; + + case PacketType.ImprovedTerseObjectUpdate: + ImprovedTerseObjectUpdatePacket itoup = (ImprovedTerseObjectUpdatePacket)packet; + + foreach (ImprovedTerseObjectUpdatePacket.ObjectDataBlock itoupod in itoup.ObjectData) + ReturnDataBlock(itoupod); + + itoup.ObjectData = null; + break; + } + } + + if (packetPoolEnabled) + { + switch (packet.Type) + { + // List pooling packets here + case PacketType.PacketAck: + case PacketType.ObjectUpdate: + case PacketType.ImprovedTerseObjectUpdate: + lock (pool) + { + PacketType type = packet.Type; + + if (!pool.ContainsKey(type)) + { + pool[type] = new Stack(); + } + + if ((pool[type]).Count < 50) + { + (pool[type]).Push(packet); + } + } + break; + + // Other packets wont pool + default: + return; + } + } + } + + public static T GetDataBlock() where T: new() + { + lock (DataBlocks) + { + Stack s; + + if (DataBlocks.TryGetValue(typeof(T), out s)) + { + if (s.Count > 0) + return (T)s.Pop(); + } + else + { + DataBlocks[typeof(T)] = new Stack(); + } + + return new T(); + } + } + + public static void ReturnDataBlock(T block) where T: new() + { + if (block == null) + return; + + lock (DataBlocks) + { + if (!DataBlocks.ContainsKey(typeof(T))) + DataBlocks[typeof(T)] = new Stack(); + + if (DataBlocks[typeof(T)].Count < 50) + DataBlocks[typeof(T)].Push(block); + } + } + } +} \ No newline at end of file -- cgit v1.1 From 7c7cdf3431c1c8ee1575779f96980ac1d0de6be8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 01:43:29 +0100 Subject: Read PacketPool config in LLUDPServer with other config params rather than in Scene. This is to resolve previous build break. This unnecessarily but harmlessly reads and sets the parameter multiple times - scene was doing the same thing. --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 55780d6..d11fcbf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -222,6 +222,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_pausedAckTimeout = 1000 * 300; // 5 minutes } + // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers. + // However, there is no harm in temporarily doing it multiple times. + IConfig packetConfig = configSource.Configs["PacketPool"]; + if (packetConfig != null) + { + PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); + PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); + } + #region BinaryStats config = configSource.Configs["Statistics.Binary"]; m_shouldCollectStats = false; -- cgit v1.1 From 16c9c1dff7bbf299efddd44e4f9aeeb7db38fff6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 6 Oct 2012 02:34:49 +0100 Subject: On receiving TaskInventoryAccepted with a destination folder in the binary bucket slot for RLV, notify the viewer about inventory folder updates. The viewer would not see the folder move without this, either on accept or decline. This commit also updates the TaskInventoryOffered message to better conform with the data LL uses Changes are, agentID is prim owner rather than prim id, agent name is now simply object name rather than name with owner detail, message is just folder name in single quotes, message is not timestamped. However, folder is not renamed "still #RLV/~". Long term solution is probably not to do these operations server-side. Notes will be added to http://opensimulator.org/mantis/view.php?id=6311 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d05ffea..0869bd5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5862,7 +5862,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP msgpack.MessageBlock.ID, msgpack.MessageBlock.Offline != 0 ? true : false, msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket); + msgpack.MessageBlock.BinaryBucket, + true); handlerInstantMessage(this, im); } -- cgit v1.1