aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs18
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs11
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs249
-rw-r--r--OpenSim/Region/ClientStack/RegionApplicationBase.cs2
5 files changed, 270 insertions, 12 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index cd70410..d604cf6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
94 UUID spId = TestHelpers.ParseTail(0x1); 94 UUID spId = TestHelpers.ParseTail(0x1);
95 95
96 SceneHelpers.AddScenePresence(m_scene, spId); 96 SceneHelpers.AddScenePresence(m_scene, spId);
97 m_scene.IncomingCloseAgent(spId); 97 m_scene.IncomingCloseAgent(spId, false);
98 98
99 // TODO: Add more assertions for the other aspects of event queues 99 // TODO: Add more assertions for the other aspects of event queues
100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index ee28914..6ccabf1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -509,19 +509,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
509 /// </summary> 509 /// </summary>
510 public void Close() 510 public void Close()
511 { 511 {
512 Close(true); 512 Close(true, false);
513 } 513 }
514 514
515 /// <summary> 515 public void Close(bool sendStop, bool force)
516 /// Shut down the client view
517 /// </summary>
518 public void Close(bool sendStop)
519 { 516 {
520 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 517 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
521 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 518 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
522 lock (CloseSyncLock) 519 lock (CloseSyncLock)
523 { 520 {
524 if (!IsActive) 521 // We still perform a force close inside the sync lock since this is intended to attempt close where
522 // there is some unidentified connection problem, not where we have issues due to deadlock
523 if (!IsActive && !force)
525 return; 524 return;
526 525
527 IsActive = false; 526 IsActive = false;
@@ -4534,7 +4533,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4534 { 4533 {
4535 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); 4534 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4536 } 4535 }
4537 j = 0; 4536 j = 0;
4538 4537
4539 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4538 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4540 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4539 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@@ -5963,7 +5962,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5963 msgpack.MessageBlock.ID, 5962 msgpack.MessageBlock.ID,
5964 msgpack.MessageBlock.Offline != 0 ? true : false, 5963 msgpack.MessageBlock.Offline != 0 ? true : false,
5965 msgpack.MessageBlock.Position, 5964 msgpack.MessageBlock.Position,
5966 msgpack.MessageBlock.BinaryBucket); 5965 msgpack.MessageBlock.BinaryBucket,
5966 true);
5967 5967
5968 handlerInstantMessage(this, im); 5968 handlerInstantMessage(this, im);
5969 } 5969 }
@@ -12193,7 +12193,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12193 { 12193 {
12194 Kick(reason); 12194 Kick(reason);
12195 Thread.Sleep(1000); 12195 Thread.Sleep(1000);
12196 Close(); 12196 Disconnect();
12197 } 12197 }
12198 12198
12199 public void Disconnect() 12199 public void Disconnect()
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index d6513c5..b3db064 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -227,6 +227,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
227 m_pausedAckTimeout = 1000 * 300; // 5 minutes 227 m_pausedAckTimeout = 1000 * 300; // 5 minutes
228 } 228 }
229 229
230 // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers.
231 // However, there is no harm in temporarily doing it multiple times.
232 IConfig packetConfig = configSource.Configs["PacketPool"];
233 if (packetConfig != null)
234 {
235 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
236 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
237 }
238
230 #region BinaryStats 239 #region BinaryStats
231 config = configSource.Configs["Statistics.Binary"]; 240 config = configSource.Configs["Statistics.Binary"];
232 m_shouldCollectStats = false; 241 m_shouldCollectStats = false;
@@ -1523,7 +1532,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1523 if (!client.IsLoggingOut) 1532 if (!client.IsLoggingOut)
1524 { 1533 {
1525 client.IsLoggingOut = true; 1534 client.IsLoggingOut = true;
1526 client.Close(false); 1535 client.Close(false, false);
1527 } 1536 }
1528 } 1537 }
1529 } 1538 }
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 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using OpenMetaverse.Packets;
33using log4net;
34
35namespace OpenSim.Region.ClientStack.LindenUDP
36{
37 public sealed class PacketPool
38 {
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40
41 private static readonly PacketPool instance = new PacketPool();
42
43 private bool packetPoolEnabled = true;
44 private bool dataBlockPoolEnabled = true;
45
46 /// <summary>
47 /// Pool of packets available for reuse.
48 /// </summary>
49 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>();
50
51 private static Dictionary<Type, Stack<Object>> DataBlocks =
52 new Dictionary<Type, Stack<Object>>();
53
54 static PacketPool()
55 {
56 }
57
58 public static PacketPool Instance
59 {
60 get { return instance; }
61 }
62
63 public bool RecyclePackets
64 {
65 set { packetPoolEnabled = value; }
66 get { return packetPoolEnabled; }
67 }
68
69 public bool RecycleDataBlocks
70 {
71 set { dataBlockPoolEnabled = value; }
72 get { return dataBlockPoolEnabled; }
73 }
74
75 public Packet GetPacket(PacketType type)
76 {
77 Packet packet;
78
79 if (!packetPoolEnabled)
80 return Packet.BuildPacket(type);
81
82 lock (pool)
83 {
84 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
85 {
86 // Creating a new packet if we cannot reuse an old package
87 packet = Packet.BuildPacket(type);
88 }
89 else
90 {
91 // Recycle old packages
92 packet = (pool[type]).Pop();
93 }
94 }
95
96 return packet;
97 }
98
99 // private byte[] decoded_header = new byte[10];
100 private static PacketType GetType(byte[] bytes)
101 {
102 byte[] decoded_header = new byte[10 + 8];
103 ushort id;
104 PacketFrequency freq;
105
106 if ((bytes[0] & Helpers.MSG_ZEROCODED) != 0)
107 {
108 Helpers.ZeroDecode(bytes, 16, decoded_header);
109 }
110 else
111 {
112 Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10);
113 }
114
115 if (decoded_header[6] == 0xFF)
116 {
117 if (decoded_header[7] == 0xFF)
118 {
119 id = (ushort) ((decoded_header[8] << 8) + decoded_header[9]);
120 freq = PacketFrequency.Low;
121 }
122 else
123 {
124 id = decoded_header[7];
125 freq = PacketFrequency.Medium;
126 }
127 }
128 else
129 {
130 id = decoded_header[6];
131 freq = PacketFrequency.High;
132 }
133
134 return Packet.GetType(id, freq);
135 }
136
137 public Packet GetPacket(byte[] bytes, ref int packetEnd, byte[] zeroBuffer)
138 {
139 PacketType type = GetType(bytes);
140
141 Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
142
143 int i = 0;
144 Packet packet = GetPacket(type);
145 if (packet == null)
146 m_log.WarnFormat("[PACKETPOOL]: Failed to get packet of type {0}", type);
147 else
148 packet.FromBytes(bytes, ref i, ref packetEnd, zeroBuffer);
149
150 return packet;
151 }
152
153 /// <summary>
154 /// Return a packet to the packet pool
155 /// </summary>
156 /// <param name="packet"></param>
157 public void ReturnPacket(Packet packet)
158 {
159 if (dataBlockPoolEnabled)
160 {
161 switch (packet.Type)
162 {
163 case PacketType.ObjectUpdate:
164 ObjectUpdatePacket oup = (ObjectUpdatePacket)packet;
165
166 foreach (ObjectUpdatePacket.ObjectDataBlock oupod in oup.ObjectData)
167 ReturnDataBlock<ObjectUpdatePacket.ObjectDataBlock>(oupod);
168
169 oup.ObjectData = null;
170 break;
171
172 case PacketType.ImprovedTerseObjectUpdate:
173 ImprovedTerseObjectUpdatePacket itoup = (ImprovedTerseObjectUpdatePacket)packet;
174
175 foreach (ImprovedTerseObjectUpdatePacket.ObjectDataBlock itoupod in itoup.ObjectData)
176 ReturnDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(itoupod);
177
178 itoup.ObjectData = null;
179 break;
180 }
181 }
182
183 if (packetPoolEnabled)
184 {
185 switch (packet.Type)
186 {
187 // List pooling packets here
188 case PacketType.PacketAck:
189 case PacketType.ObjectUpdate:
190 case PacketType.ImprovedTerseObjectUpdate:
191 lock (pool)
192 {
193 PacketType type = packet.Type;
194
195 if (!pool.ContainsKey(type))
196 {
197 pool[type] = new Stack<Packet>();
198 }
199
200 if ((pool[type]).Count < 50)
201 {
202 (pool[type]).Push(packet);
203 }
204 }
205 break;
206
207 // Other packets wont pool
208 default:
209 return;
210 }
211 }
212 }
213
214 public static T GetDataBlock<T>() where T: new()
215 {
216 lock (DataBlocks)
217 {
218 Stack<Object> s;
219
220 if (DataBlocks.TryGetValue(typeof(T), out s))
221 {
222 if (s.Count > 0)
223 return (T)s.Pop();
224 }
225 else
226 {
227 DataBlocks[typeof(T)] = new Stack<Object>();
228 }
229
230 return new T();
231 }
232 }
233
234 public static void ReturnDataBlock<T>(T block) where T: new()
235 {
236 if (block == null)
237 return;
238
239 lock (DataBlocks)
240 {
241 if (!DataBlocks.ContainsKey(typeof(T)))
242 DataBlocks[typeof(T)] = new Stack<Object>();
243
244 if (DataBlocks[typeof(T)].Count < 50)
245 DataBlocks[typeof(T)].Push(block);
246 }
247 }
248 }
249} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index 4672f8a..853b72d 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack
76 76
77 protected override void StartupSpecific() 77 protected override void StartupSpecific()
78 { 78 {
79 SceneManager = new SceneManager(); 79 SceneManager = SceneManager.Instance;
80 m_clientStackManager = CreateClientStackManager(); 80 m_clientStackManager = CreateClientStackManager();
81 81
82 Initialize(); 82 Initialize();