aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs308
1 files changed, 308 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
new file mode 100644
index 0000000..8c967a2
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -0,0 +1,308 @@
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 OpenSim 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;
30using System.Collections.Generic;
31using System.Threading;
32using libsecondlife;
33using OpenSim.Framework;
34using OpenSim.Region.Environment.Interfaces;
35using OpenSim.Region.ScriptEngine.Interfaces;
36using OpenSim.Region.ScriptEngine.Shared;
37using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
38using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
39
40namespace OpenSim.Region.ScriptEngine.Shared.Api
41{
42 /// <summary>
43 /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
44 /// </summary>
45 public class AsyncCommandManager
46 {
47 private static Thread cmdHandlerThread;
48 private static int cmdHandlerThreadCycleSleepms;
49
50 private static List<AsyncCommandManager> m_Managers = new List<AsyncCommandManager>();
51 public IScriptEngine m_ScriptEngine;
52
53 private Dataserver m_Dataserver;
54 private Timer m_Timer;
55 private HttpRequest m_HttpRequest;
56 private Listener m_Listener;
57 private SensorRepeat m_SensorRepeat;
58 private XmlRequest m_XmlRequest;
59
60 public Dataserver DataserverPlugin
61 {
62 get { return m_Dataserver; }
63 }
64
65 public Timer TimerPlugin
66 {
67 get { return m_Timer; }
68 }
69
70 public HttpRequest HttpRequestPlugin
71 {
72 get { return m_HttpRequest; }
73 }
74
75 public Listener ListenerPlugin
76 {
77 get { return m_Listener; }
78 }
79
80 public SensorRepeat SensorRepeatPlugin
81 {
82 get { return m_SensorRepeat; }
83 }
84
85 public XmlRequest XmlRequestPlugin
86 {
87 get { return m_XmlRequest; }
88 }
89
90 public AsyncCommandManager[] Managers
91 {
92 get { return m_Managers.ToArray(); }
93 }
94
95 public AsyncCommandManager(IScriptEngine _ScriptEngine)
96 {
97 m_ScriptEngine = _ScriptEngine;
98 if(!m_Managers.Contains(this))
99 m_Managers.Add(this);
100
101 ReadConfig();
102
103 // Create instances of all plugins
104 m_Dataserver = new Dataserver(this);
105 m_Timer = new Timer(this);
106 m_HttpRequest = new HttpRequest(this);
107 m_Listener = new Listener(this);
108 m_SensorRepeat = new SensorRepeat(this);
109 m_XmlRequest = new XmlRequest(this);
110
111 StartThread();
112 }
113
114 private static void StartThread()
115 {
116 if (cmdHandlerThread == null)
117 {
118 // Start the thread that will be doing the work
119 cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
120 cmdHandlerThread.Name = "AsyncLSLCmdHandlerThread";
121 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
122 cmdHandlerThread.IsBackground = true;
123 cmdHandlerThread.Start();
124 ThreadTracker.Add(cmdHandlerThread);
125 }
126 }
127
128 public void ReadConfig()
129 {
130 cmdHandlerThreadCycleSleepms = m_ScriptEngine.Config.GetInt("AsyncLLCommandLoopms", 100);
131 }
132
133 ~AsyncCommandManager()
134 {
135 // Shut down thread
136 try
137 {
138 if (cmdHandlerThread != null)
139 {
140 if (cmdHandlerThread.IsAlive == true)
141 {
142 cmdHandlerThread.Abort();
143 //cmdHandlerThread.Join();
144 }
145 }
146 }
147 catch
148 {
149 }
150 }
151
152 private static void CmdHandlerThreadLoop()
153 {
154 while (true)
155 {
156 try
157 {
158 while (true)
159 {
160 Thread.Sleep(cmdHandlerThreadCycleSleepms);
161
162 foreach (AsyncCommandManager m in m_Managers)
163 {
164 m.DoOneCmdHandlerPass();
165 }
166 }
167 }
168 catch
169 {
170 }
171 }
172 }
173
174 public void DoOneCmdHandlerPass()
175 {
176 // Check timers
177 m_Timer.CheckTimerEvents();
178 // Check HttpRequests
179 m_HttpRequest.CheckHttpRequests();
180 // Check XMLRPCRequests
181 m_XmlRequest.CheckXMLRPCRequests();
182 // Check Listeners
183 m_Listener.CheckListeners();
184 // Check Sensors
185 m_SensorRepeat.CheckSenseRepeaterEvents();
186 // Check dataserver
187 m_Dataserver.ExpireRequests();
188 }
189
190 /// <summary>
191 /// Remove a specific script (and all its pending commands)
192 /// </summary>
193 /// <param name="localID"></param>
194 /// <param name="itemID"></param>
195 public void RemoveScript(uint localID, LLUUID itemID)
196 {
197 // Remove a specific script
198
199 // Remove dataserver events
200 m_Dataserver.RemoveEvents(localID, itemID);
201
202 // Remove from: Timers
203 m_Timer.UnSetTimerEvents(localID, itemID);
204
205 // Remove from: HttpRequest
206 IHttpRequests iHttpReq =
207 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
208 iHttpReq.StopHttpRequest(localID, itemID);
209
210 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
211 comms.DeleteListener(itemID);
212
213 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
214 xmlrpc.DeleteChannels(itemID);
215 xmlrpc.CancelSRDRequests(itemID);
216
217 // Remove Sensors
218 m_SensorRepeat.UnSetSenseRepeaterEvents(localID, itemID);
219
220 }
221
222 public Object[] GetSerializationData(LLUUID itemID)
223 {
224 List<Object> data = new List<Object>();
225
226 Object[] listeners=m_Listener.GetSerializationData(itemID);
227 if (listeners.Length > 0)
228 {
229 data.Add("listener");
230 data.Add(listeners.Length);
231 data.AddRange(listeners);
232 }
233
234 Object[] timers=m_Timer.GetSerializationData(itemID);
235 if (timers.Length > 0)
236 {
237 data.Add("timer");
238 data.Add(timers.Length);
239 data.AddRange(timers);
240 }
241
242 Object[] sensors=m_SensorRepeat.GetSerializationData(itemID);
243 if (sensors.Length > 0)
244 {
245 data.Add("sensor");
246 data.Add(sensors.Length);
247 data.AddRange(sensors);
248 }
249
250 return data.ToArray();
251 }
252
253 public void CreateFromData(uint localID, LLUUID itemID, LLUUID hostID,
254 Object[] data)
255 {
256 int idx = 0;
257 int len;
258
259 while (idx < data.Length)
260 {
261 string type = data[idx].ToString();
262 len = (int)data[idx+1];
263 idx+=2;
264
265 if (len > 0)
266 {
267 Object[] item = new Object[len];
268 Array.Copy(data, idx, item, 0, len);
269
270 idx+=len;
271
272 switch (type)
273 {
274 case "listener":
275 m_Listener.CreateFromData(localID, itemID, hostID,
276 item);
277 break;
278 case "timer":
279 m_Timer.CreateFromData(localID, itemID, hostID, item);
280 break;
281 case "sensor":
282 m_SensorRepeat.CreateFromData(localID, itemID, hostID,
283 item);
284 break;
285 }
286 }
287 }
288 }
289
290 #region Check llRemoteData channels
291
292 #endregion
293
294 #region Check llListeners
295
296 #endregion
297
298 /// <summary>
299 /// If set to true then threads and stuff should try to make a graceful exit
300 /// </summary>
301 public bool PleaseShutdown
302 {
303 get { return _PleaseShutdown; }
304 set { _PleaseShutdown = value; }
305 }
306 private bool _PleaseShutdown = false;
307 }
308}