aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2014-11-05 19:02:26 +0000
committerJustin Clark-Casey (justincc)2014-11-25 23:23:11 +0000
commitd6c9705a3b9d4c9bbe0e23f6d8d3793c07bf53ea (patch)
treeb2c2782d4825c5b407fef7e9d57d96d07852910a /OpenSim/Region/ClientStack/Linden/UDP
parentAdd missing class from recent commit 69abade (diff)
downloadopensim-SC_OLD-d6c9705a3b9d4c9bbe0e23f6d8d3793c07bf53ea.zip
opensim-SC_OLD-d6c9705a3b9d4c9bbe0e23f6d8d3793c07bf53ea.tar.gz
opensim-SC_OLD-d6c9705a3b9d4c9bbe0e23f6d8d3793c07bf53ea.tar.bz2
opensim-SC_OLD-d6c9705a3b9d4c9bbe0e23f6d8d3793c07bf53ea.tar.xz
Add incoming packet async handling engine to queue some inbound udp async requests.
This is to reduce the potential for overload of the threadpool if there are many simultaneous requets in high concurrency situations. Currently only applied to AvatarProperties and GenericMessage requests.
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacketAsyncHandlingEngine.cs328
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs67
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs9
3 files changed, 393 insertions, 11 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacketAsyncHandlingEngine.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacketAsyncHandlingEngine.cs
new file mode 100644
index 0000000..874ddae
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacketAsyncHandlingEngine.cs
@@ -0,0 +1,328 @@
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.Concurrent;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
35using OpenSim.Region.Framework.Scenes;
36
37namespace OpenSim.Region.ClientStack.LindenUDP
38{
39 public class Job
40 {
41 public string Name;
42 public WaitCallback Callback;
43 public object O;
44
45 public Job(string name, WaitCallback callback, object o)
46 {
47 Name = name;
48 Callback = callback;
49 O = o;
50 }
51 }
52
53 // TODO: These kinds of classes MUST be generalized with JobEngine, etc.
54 public class IncomingPacketAsyncHandlingEngine
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57
58 public int LogLevel { get; set; }
59
60 public bool IsRunning { get; private set; }
61
62 /// <summary>
63 /// The timeout in milliseconds to wait for at least one event to be written when the recorder is stopping.
64 /// </summary>
65 public int RequestProcessTimeoutOnStop { get; set; }
66
67 /// <summary>
68 /// Controls whether we need to warn in the log about exceeding the max queue size.
69 /// </summary>
70 /// <remarks>
71 /// This is flipped to false once queue max has been exceeded and back to true when it falls below max, in
72 /// order to avoid spamming the log with lots of warnings.
73 /// </remarks>
74 private bool m_warnOverMaxQueue = true;
75
76 private BlockingCollection<Job> m_requestQueue;
77
78 private CancellationTokenSource m_cancelSource = new CancellationTokenSource();
79
80 private LLUDPServer m_udpServer;
81
82 private Stat m_requestsWaitingStat;
83
84 private Job m_currentJob;
85
86 /// <summary>
87 /// Used to signal that we are ready to complete stop.
88 /// </summary>
89 private ManualResetEvent m_finishedProcessingAfterStop = new ManualResetEvent(false);
90
91 public IncomingPacketAsyncHandlingEngine(LLUDPServer server)
92 {
93 //LogLevel = 1;
94 m_udpServer = server;
95 RequestProcessTimeoutOnStop = 5000;
96
97 // MainConsole.Instance.Commands.AddCommand(
98 // "Debug",
99 // false,
100 // "debug jobengine",
101 // "debug jobengine <start|stop|status>",
102 // "Start, stop or get status of the job engine.",
103 // "If stopped then all jobs are processed immediately.",
104 // HandleControlCommand);
105 }
106
107 public void Start()
108 {
109 lock (this)
110 {
111 if (IsRunning)
112 return;
113
114 IsRunning = true;
115
116 m_finishedProcessingAfterStop.Reset();
117
118 m_requestQueue = new BlockingCollection<Job>(new ConcurrentQueue<Job>(), 5000);
119
120 m_requestsWaitingStat =
121 new Stat(
122 "IncomingPacketAsyncRequestsWaiting",
123 "Number of incoming packets waiting for async processing in engine.",
124 "",
125 "",
126 "clientstack",
127 m_udpServer.Scene.Name,
128 StatType.Pull,
129 MeasuresOfInterest.None,
130 stat => stat.Value = m_requestQueue.Count,
131 StatVerbosity.Debug);
132
133 StatsManager.RegisterStat(m_requestsWaitingStat);
134
135 Watchdog.StartThread(
136 ProcessRequests,
137 string.Format("Incoming Packet Async Handling Engine Thread ({0})", m_udpServer.Scene.Name),
138 ThreadPriority.Normal,
139 false,
140 true,
141 null,
142 int.MaxValue);
143 }
144 }
145
146 public void Stop()
147 {
148 lock (this)
149 {
150 try
151 {
152 if (!IsRunning)
153 return;
154
155 IsRunning = false;
156
157 int requestsLeft = m_requestQueue.Count;
158
159 if (requestsLeft <= 0)
160 {
161 m_cancelSource.Cancel();
162 }
163 else
164 {
165 m_log.InfoFormat("[INCOMING PACKET ASYNC HANDLING ENGINE]: Waiting to write {0} events after stop.", requestsLeft);
166
167 while (requestsLeft > 0)
168 {
169 if (!m_finishedProcessingAfterStop.WaitOne(RequestProcessTimeoutOnStop))
170 {
171 // After timeout no events have been written
172 if (requestsLeft == m_requestQueue.Count)
173 {
174 m_log.WarnFormat(
175 "[INCOMING PACKET ASYNC HANDLING ENGINE]: No requests processed after {0} ms wait. Discarding remaining {1} requests",
176 RequestProcessTimeoutOnStop, requestsLeft);
177
178 break;
179 }
180 }
181
182 requestsLeft = m_requestQueue.Count;
183 }
184 }
185 }
186 finally
187 {
188 m_cancelSource.Dispose();
189 StatsManager.DeregisterStat(m_requestsWaitingStat);
190 m_requestsWaitingStat = null;
191 m_requestQueue = null;
192 }
193 }
194 }
195
196 public bool QueueRequest(string name, WaitCallback req, object o)
197 {
198 if (LogLevel >= 1)
199 m_log.DebugFormat("[INCOMING PACKET ASYNC HANDLING ENGINE]: Queued job {0}", name);
200
201 if (m_requestQueue.Count < m_requestQueue.BoundedCapacity)
202 {
203 // m_log.DebugFormat(
204 // "[OUTGOING QUEUE REFILL ENGINE]: Adding request for categories {0} for {1} in {2}",
205 // categories, client.AgentID, m_udpServer.Scene.Name);
206
207 m_requestQueue.Add(new Job(name, req, o));
208
209 if (!m_warnOverMaxQueue)
210 m_warnOverMaxQueue = true;
211
212 return true;
213 }
214 else
215 {
216 if (m_warnOverMaxQueue)
217 {
218 // m_log.WarnFormat(
219 // "[JOB ENGINE]: Request queue at maximum capacity, not recording request from {0} in {1}",
220 // client.AgentID, m_udpServer.Scene.Name);
221
222 m_log.WarnFormat("[INCOMING PACKET ASYNC HANDLING ENGINE]: Request queue at maximum capacity, not recording job");
223
224 m_warnOverMaxQueue = false;
225 }
226
227 return false;
228 }
229 }
230
231 private void ProcessRequests()
232 {
233 try
234 {
235 while (IsRunning || m_requestQueue.Count > 0)
236 {
237 m_currentJob = m_requestQueue.Take(m_cancelSource.Token);
238
239 // QueueEmpty callback = req.Client.OnQueueEmpty;
240 //
241 // if (callback != null)
242 // {
243 // try
244 // {
245 // callback(req.Categories);
246 // }
247 // catch (Exception e)
248 // {
249 // m_log.Error("[OUTGOING QUEUE REFILL ENGINE]: ProcessRequests(" + req.Categories + ") threw an exception: " + e.Message, e);
250 // }
251 // }
252
253 if (LogLevel >= 1)
254 m_log.DebugFormat("[INCOMING PACKET ASYNC HANDLING ENGINE]: Processing job {0}", m_currentJob.Name);
255
256 try
257 {
258 m_currentJob.Callback.Invoke(m_currentJob.O);
259 }
260 catch (Exception e)
261 {
262 m_log.Error(
263 string.Format(
264 "[INCOMING PACKET ASYNC HANDLING ENGINE]: Job {0} failed, continuing. Exception ", m_currentJob.Name), e);
265 }
266
267 if (LogLevel >= 1)
268 m_log.DebugFormat("[INCOMING PACKET ASYNC HANDLING ENGINE]: Processed job {0}", m_currentJob.Name);
269
270 m_currentJob = null;
271 }
272 }
273 catch (OperationCanceledException)
274 {
275 }
276
277 m_finishedProcessingAfterStop.Set();
278 }
279
280 // private void HandleControlCommand(string module, string[] args)
281 // {
282 // // if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
283 // // return;
284 //
285 // if (args.Length < 3)
286 // {
287 // MainConsole.Instance.Output("Usage: debug jobengine <stop|start|status|loglevel>");
288 // return;
289 // }
290 //
291 // string subCommand = args[2];
292 //
293 // if (subCommand == "stop")
294 // {
295 // Stop();
296 // MainConsole.Instance.OutputFormat("Stopped job engine.");
297 // }
298 // else if (subCommand == "start")
299 // {
300 // Start();
301 // MainConsole.Instance.OutputFormat("Started job engine.");
302 // }
303 // else if (subCommand == "status")
304 // {
305 // MainConsole.Instance.OutputFormat("Job engine running: {0}", IsRunning);
306 // MainConsole.Instance.OutputFormat("Current job {0}", m_currentJob != null ? m_currentJob.Name : "none");
307 // MainConsole.Instance.OutputFormat(
308 // "Jobs waiting: {0}", IsRunning ? m_requestQueue.Count.ToString() : "n/a");
309 // MainConsole.Instance.OutputFormat("Log Level: {0}", LogLevel);
310 // }
311 //
312 // else if (subCommand == "loglevel")
313 // {
314 // // int logLevel;
315 // int logLevel = int.Parse(args[3]);
316 // // if (ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out logLevel))
317 // // {
318 // LogLevel = logLevel;
319 // MainConsole.Instance.OutputFormat("Set log level to {0}", LogLevel);
320 // // }
321 // }
322 // else
323 // {
324 // MainConsole.Instance.OutputFormat("Unrecognized job engine subcommand {0}", subCommand);
325 // }
326 // }
327 }
328}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 516327c..85f9d68 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -648,12 +648,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
648 /// <returns>true if the handler was added. This is currently always the case.</returns> 648 /// <returns>true if the handler was added. This is currently always the case.</returns>
649 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync) 649 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync)
650 { 650 {
651 return AddLocalPacketHandler(packetType, handler, doAsync, false);
652 }
653
654 /// <summary>
655 /// Add a handler for the given packet type.
656 /// </summary>
657 /// <param name="packetType"></param>
658 /// <param name="handler"></param>
659 /// <param name="doAsync">
660 /// If true, when the packet is received handle it on a different thread. Whether this is given direct to
661 /// a threadpool thread or placed in a queue depends on the inEngine parameter.
662 /// </param>
663 /// <param name="inEngine">
664 /// If async is false then this parameter is ignored.
665 /// If async is true and inEngine is false, then the packet is sent directly to a
666 /// threadpool thread.
667 /// If async is true and inEngine is true, then the packet is sent to the IncomingPacketAsyncHandlingEngine.
668 /// This may result in slower handling but reduces the risk of overloading the simulator when there are many
669 /// simultaneous async requests.
670 /// </param>
671 /// <returns>true if the handler was added. This is currently always the case.</returns>
672 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync, bool inEngine)
673 {
651 bool result = false; 674 bool result = false;
652 lock (m_packetHandlers) 675 lock (m_packetHandlers)
653 { 676 {
654 if (!m_packetHandlers.ContainsKey(packetType)) 677 if (!m_packetHandlers.ContainsKey(packetType))
655 { 678 {
656 m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = doAsync }); 679 m_packetHandlers.Add(
680 packetType, new PacketProcessor() { method = handler, Async = doAsync, InEngine = inEngine });
657 result = true; 681 result = true;
658 } 682 }
659 } 683 }
@@ -688,21 +712,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
688 PacketProcessor pprocessor; 712 PacketProcessor pprocessor;
689 if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor)) 713 if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor))
690 { 714 {
715 ClientInfo cinfo = UDPClient.GetClientInfo();
716
691 //there is a local handler for this packet type 717 //there is a local handler for this packet type
692 if (pprocessor.Async) 718 if (pprocessor.Async)
693 { 719 {
694 ClientInfo cinfo = UDPClient.GetClientInfo();
695 if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString())) 720 if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString()))
696 cinfo.AsyncRequests[packet.Type.ToString()] = 0; 721 cinfo.AsyncRequests[packet.Type.ToString()] = 0;
697 cinfo.AsyncRequests[packet.Type.ToString()]++; 722 cinfo.AsyncRequests[packet.Type.ToString()]++;
698 723
699 object obj = new AsyncPacketProcess(this, pprocessor.method, packet); 724 object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
700 Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString()); 725
726 if (pprocessor.InEngine)
727 m_udpServer.IpahEngine.QueueRequest(
728 packet.Type.ToString(),
729 ProcessSpecificPacketAsync,
730 obj);
731 else
732 Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString());
733
701 result = true; 734 result = true;
702 } 735 }
703 else 736 else
704 { 737 {
705 ClientInfo cinfo = UDPClient.GetClientInfo();
706 if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString())) 738 if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString()))
707 cinfo.SyncRequests[packet.Type.ToString()] = 0; 739 cinfo.SyncRequests[packet.Type.ToString()] = 0;
708 cinfo.SyncRequests[packet.Type.ToString()]++; 740 cinfo.SyncRequests[packet.Type.ToString()]++;
@@ -5554,10 +5586,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5554 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); 5586 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5555 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); 5587 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
5556 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); 5588 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
5557 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); 5589 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage, true, true);
5558 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); 5590 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest, true, true);
5559 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5591 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
5560 AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); 5592 AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate, true, true);
5561 AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); 5593 AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
5562 AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage); 5594 AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage);
5563 AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); 5595 AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
@@ -5742,8 +5774,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5742 AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete); 5774 AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete);
5743 AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete); 5775 AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete);
5744 AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate); 5776 AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate);
5745 AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate); 5777 AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate, true, true);
5746 AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate); 5778 AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate, true, true);
5747 AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights); 5779 AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights);
5748 AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery); 5780 AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery);
5749 AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry); 5781 AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry);
@@ -12801,8 +12833,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12801 12833
12802 public struct PacketProcessor 12834 public struct PacketProcessor
12803 { 12835 {
12804 public PacketMethod method; 12836 /// <summary>
12805 public bool Async; 12837 /// Packet handling method.
12838 /// </summary>
12839 public PacketMethod method { get; set; }
12840
12841 /// <summary>
12842 /// Should this packet be handled asynchronously?
12843 /// </summary>
12844 public bool Async { get; set; }
12845
12846 /// <summary>
12847 /// If async is true, should this packet be handled in the async engine or given directly to a threadpool
12848 /// thread?
12849 /// </summary>
12850 public bool InEngine { get; set; }
12806 } 12851 }
12807 12852
12808 public class AsyncPacketProcess 12853 public class AsyncPacketProcess
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 61e1d6a..d8cf7a5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -364,6 +364,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
364 private IClientAPI m_currentIncomingClient; 364 private IClientAPI m_currentIncomingClient;
365 365
366 /// <summary> 366 /// <summary>
367 /// Queue some low priority but potentially high volume async requests so that they don't overwhelm available
368 /// threadpool threads.
369 /// </summary>
370 public IncomingPacketAsyncHandlingEngine IpahEngine { get; private set; }
371
372 /// <summary>
367 /// Experimental facility to run queue empty processing within a controlled number of threads rather than 373 /// Experimental facility to run queue empty processing within a controlled number of threads rather than
368 /// requiring massive numbers of short-lived threads from the threadpool when there are a high number of 374 /// requiring massive numbers of short-lived threads from the threadpool when there are a high number of
369 /// connections. 375 /// connections.
@@ -454,6 +460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
454 if (usePools) 460 if (usePools)
455 EnablePools(); 461 EnablePools();
456 462
463 IpahEngine = new IncomingPacketAsyncHandlingEngine(this);
457 OqrEngine = new OutgoingQueueRefillEngine(this); 464 OqrEngine = new OutgoingQueueRefillEngine(this);
458 } 465 }
459 466
@@ -461,6 +468,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 { 468 {
462 StartInbound(); 469 StartInbound();
463 StartOutbound(); 470 StartOutbound();
471 IpahEngine.Start();
464 OqrEngine.Start(); 472 OqrEngine.Start();
465 473
466 m_elapsedMSSinceLastStatReport = Environment.TickCount; 474 m_elapsedMSSinceLastStatReport = Environment.TickCount;
@@ -506,6 +514,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
506 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name); 514 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name);
507 base.StopOutbound(); 515 base.StopOutbound();
508 base.StopInbound(); 516 base.StopInbound();
517 IpahEngine.Stop();
509 OqrEngine.Stop(); 518 OqrEngine.Stop();
510 } 519 }
511 520