aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs624
1 files changed, 312 insertions, 312 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
index 5ec8f50..c8b1256 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
@@ -1,313 +1,313 @@
1/* 1/*
2* Copyright (c) Contributors, http://opensimulator.org/ 2* Copyright (c) Contributors, http://opensimulator.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders. 3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4* 4*
5* Redistribution and use in source and binary forms, with or without 5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met: 6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright 7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer. 8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright 9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the 10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution. 11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the 12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products 13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission. 14* derived from this software without specific prior written permission.
15* 15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY 16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26* 26*
27*/ 27*/
28 28
29using System; 29using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Threading; 31using System.Threading;
32using libsecondlife; 32using libsecondlife;
33using OpenSim.Region.Environment.Interfaces; 33using OpenSim.Region.Environment.Interfaces;
34using OpenSim.Region.Environment.Modules; 34using OpenSim.Region.Environment.Modules;
35 35
36namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase 36namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
37{ 37{
38 /// <summary> 38 /// <summary>
39 /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc. 39 /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
40 /// </summary> 40 /// </summary>
41 public class AsyncLSLCommandManager : iScriptEngineFunctionModule 41 public class AsyncLSLCommandManager : iScriptEngineFunctionModule
42 { 42 {
43 private Thread cmdHandlerThread; 43 private Thread cmdHandlerThread;
44 private int cmdHandlerThreadCycleSleepms; 44 private int cmdHandlerThreadCycleSleepms;
45 45
46 private ScriptEngine m_ScriptEngine; 46 private ScriptEngine m_ScriptEngine;
47 47
48 public AsyncLSLCommandManager(ScriptEngine _ScriptEngine) 48 public AsyncLSLCommandManager(ScriptEngine _ScriptEngine)
49 { 49 {
50 m_ScriptEngine = _ScriptEngine; 50 m_ScriptEngine = _ScriptEngine;
51 ReadConfig(); 51 ReadConfig();
52 52
53 // Start the thread that will be doing the work 53 // Start the thread that will be doing the work
54 cmdHandlerThread = new Thread(CmdHandlerThreadLoop); 54 cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
55 cmdHandlerThread.Name = "CmdHandlerThread"; 55 cmdHandlerThread.Name = "CmdHandlerThread";
56 cmdHandlerThread.Priority = ThreadPriority.BelowNormal; 56 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
57 cmdHandlerThread.IsBackground = true; 57 cmdHandlerThread.IsBackground = true;
58 cmdHandlerThread.Start(); 58 cmdHandlerThread.Start();
59 } 59 }
60 60
61 public void ReadConfig() 61 public void ReadConfig()
62 { 62 {
63 cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 50); 63 cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 50);
64 } 64 }
65 65
66 66
67 ~AsyncLSLCommandManager() 67 ~AsyncLSLCommandManager()
68 { 68 {
69 // Shut down thread 69 // Shut down thread
70 try 70 try
71 { 71 {
72 if (cmdHandlerThread != null) 72 if (cmdHandlerThread != null)
73 { 73 {
74 if (cmdHandlerThread.IsAlive == true) 74 if (cmdHandlerThread.IsAlive == true)
75 { 75 {
76 cmdHandlerThread.Abort(); 76 cmdHandlerThread.Abort();
77 cmdHandlerThread.Join(); 77 cmdHandlerThread.Join();
78 } 78 }
79 } 79 }
80 } 80 }
81 catch 81 catch
82 { 82 {
83 } 83 }
84 } 84 }
85 85
86 private void CmdHandlerThreadLoop() 86 private void CmdHandlerThreadLoop()
87 { 87 {
88 while (true) 88 while (true)
89 { 89 {
90 // Check timers 90 // Check timers
91 CheckTimerEvents(); 91 CheckTimerEvents();
92 Thread.Sleep(25); 92 Thread.Sleep(25);
93 // Check HttpRequests 93 // Check HttpRequests
94 CheckHttpRequests(); 94 CheckHttpRequests();
95 Thread.Sleep(25); 95 Thread.Sleep(25);
96 // Check XMLRPCRequests 96 // Check XMLRPCRequests
97 CheckXMLRPCRequests(); 97 CheckXMLRPCRequests();
98 Thread.Sleep(25); 98 Thread.Sleep(25);
99 // Check Listeners 99 // Check Listeners
100 CheckListeners(); 100 CheckListeners();
101 Thread.Sleep(25); 101 Thread.Sleep(25);
102 102
103 // Sleep before next cycle 103 // Sleep before next cycle
104 //Thread.Sleep(cmdHandlerThreadCycleSleepms); 104 //Thread.Sleep(cmdHandlerThreadCycleSleepms);
105 } 105 }
106 } 106 }
107 107
108 /// <summary> 108 /// <summary>
109 /// Remove a specific script (and all its pending commands) 109 /// Remove a specific script (and all its pending commands)
110 /// </summary> 110 /// </summary>
111 /// <param name="m_localID"></param> 111 /// <param name="m_localID"></param>
112 /// <param name="m_itemID"></param> 112 /// <param name="m_itemID"></param>
113 public void RemoveScript(uint localID, LLUUID itemID) 113 public void RemoveScript(uint localID, LLUUID itemID)
114 { 114 {
115 // Remove a specific script 115 // Remove a specific script
116 116
117 // Remove from: Timers 117 // Remove from: Timers
118 UnSetTimerEvents(localID, itemID); 118 UnSetTimerEvents(localID, itemID);
119 // Remove from: HttpRequest 119 // Remove from: HttpRequest
120 IHttpRequests iHttpReq = 120 IHttpRequests iHttpReq =
121 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>(); 121 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
122 iHttpReq.StopHttpRequest(localID, itemID); 122 iHttpReq.StopHttpRequest(localID, itemID);
123 } 123 }
124 124
125 #region TIMER 125 #region TIMER
126 126
127 // 127 //
128 // TIMER 128 // TIMER
129 // 129 //
130 private class TimerClass 130 private class TimerClass
131 { 131 {
132 public uint localID; 132 public uint localID;
133 public LLUUID itemID; 133 public LLUUID itemID;
134 public double interval; 134 public double interval;
135 public DateTime next; 135 public DateTime next;
136 } 136 }
137 137
138 private List<TimerClass> Timers = new List<TimerClass>(); 138 private List<TimerClass> Timers = new List<TimerClass>();
139 private object TimerListLock = new object(); 139 private object TimerListLock = new object();
140 140
141 public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec) 141 public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
142 { 142 {
143 Console.WriteLine("SetTimerEvent"); 143 Console.WriteLine("SetTimerEvent");
144 144
145 // Always remove first, in case this is a re-set 145 // Always remove first, in case this is a re-set
146 UnSetTimerEvents(m_localID, m_itemID); 146 UnSetTimerEvents(m_localID, m_itemID);
147 if (sec == 0) // Disabling timer 147 if (sec == 0) // Disabling timer
148 return; 148 return;
149 149
150 // Add to timer 150 // Add to timer
151 TimerClass ts = new TimerClass(); 151 TimerClass ts = new TimerClass();
152 ts.localID = m_localID; 152 ts.localID = m_localID;
153 ts.itemID = m_itemID; 153 ts.itemID = m_itemID;
154 ts.interval = sec; 154 ts.interval = sec;
155 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 155 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
156 lock (TimerListLock) 156 lock (TimerListLock)
157 { 157 {
158 Timers.Add(ts); 158 Timers.Add(ts);
159 } 159 }
160 } 160 }
161 161
162 public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID) 162 public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
163 { 163 {
164 // Remove from timer 164 // Remove from timer
165 lock (TimerListLock) 165 lock (TimerListLock)
166 { 166 {
167 List<TimerClass> NewTimers = new List<TimerClass>(); 167 List<TimerClass> NewTimers = new List<TimerClass>();
168 foreach (TimerClass ts in Timers) 168 foreach (TimerClass ts in Timers)
169 { 169 {
170 if (ts.localID != m_localID && ts.itemID != m_itemID) 170 if (ts.localID != m_localID && ts.itemID != m_itemID)
171 { 171 {
172 NewTimers.Add(ts); 172 NewTimers.Add(ts);
173 } 173 }
174 } 174 }
175 Timers.Clear(); 175 Timers.Clear();
176 Timers = NewTimers; 176 Timers = NewTimers;
177 } 177 }
178 } 178 }
179 179
180 public void CheckTimerEvents() 180 public void CheckTimerEvents()
181 { 181 {
182 // Nothing to do here? 182 // Nothing to do here?
183 if (Timers.Count == 0) 183 if (Timers.Count == 0)
184 return; 184 return;
185 185
186 lock (TimerListLock) 186 lock (TimerListLock)
187 { 187 {
188 // Go through all timers 188 // Go through all timers
189 foreach (TimerClass ts in Timers) 189 foreach (TimerClass ts in Timers)
190 { 190 {
191 // Time has passed? 191 // Time has passed?
192 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) 192 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
193 { 193 {
194 // Add it to queue 194 // Add it to queue
195 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull, 195 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull,
196 new object[] {}); 196 new object[] {});
197 // set next interval 197 // set next interval
198 198
199 199
200 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 200 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
201 } 201 }
202 } 202 }
203 } // lock 203 } // lock
204 } 204 }
205 205
206 #endregion 206 #endregion
207 207
208 #region HTTP REQUEST 208 #region HTTP REQUEST
209 209
210 public void CheckHttpRequests() 210 public void CheckHttpRequests()
211 { 211 {
212 if (m_ScriptEngine.World == null) 212 if (m_ScriptEngine.World == null)
213 return; 213 return;
214 214
215 IHttpRequests iHttpReq = 215 IHttpRequests iHttpReq =
216 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>(); 216 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
217 217
218 HttpRequestClass httpInfo = null; 218 HttpRequestClass httpInfo = null;
219 219
220 if (iHttpReq != null) 220 if (iHttpReq != null)
221 httpInfo = iHttpReq.GetNextCompletedRequest(); 221 httpInfo = iHttpReq.GetNextCompletedRequest();
222 222
223 while (httpInfo != null) 223 while (httpInfo != null)
224 { 224 {
225 //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status); 225 //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status);
226 226
227 // Deliver data to prim's remote_data handler 227 // Deliver data to prim's remote_data handler
228 // 228 //
229 // TODO: Returning null for metadata, since the lsl function 229 // TODO: Returning null for metadata, since the lsl function
230 // only returns the byte for HTTP_BODY_TRUNCATED, which is not 230 // only returns the byte for HTTP_BODY_TRUNCATED, which is not
231 // implemented here yet anyway. Should be fixed if/when maxsize 231 // implemented here yet anyway. Should be fixed if/when maxsize
232 // is supported 232 // is supported
233 233
234 object[] resobj = new object[] 234 object[] resobj = new object[]
235 { 235 {
236 httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body 236 httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
237 }; 237 };
238 238
239 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 239 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
240 httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj 240 httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj
241 ); 241 );
242 242
243 httpInfo.Stop(); 243 httpInfo.Stop();
244 httpInfo = null; 244 httpInfo = null;
245 245
246 httpInfo = iHttpReq.GetNextCompletedRequest(); 246 httpInfo = iHttpReq.GetNextCompletedRequest();
247 } 247 }
248 } 248 }
249 249
250 #endregion 250 #endregion
251 251
252 public void CheckXMLRPCRequests() 252 public void CheckXMLRPCRequests()
253 { 253 {
254 if (m_ScriptEngine.World == null) 254 if (m_ScriptEngine.World == null)
255 return; 255 return;
256 256
257 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 257 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
258 258
259 if (xmlrpc != null) 259 if (xmlrpc != null)
260 { 260 {
261 while (xmlrpc.hasRequests()) 261 while (xmlrpc.hasRequests())
262 { 262 {
263 RPCRequestInfo rInfo = xmlrpc.GetNextRequest(); 263 RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
264 //Console.WriteLine("PICKED REQUEST"); 264 //Console.WriteLine("PICKED REQUEST");
265 265
266 //Deliver data to prim's remote_data handler 266 //Deliver data to prim's remote_data handler
267 object[] resobj = new object[] 267 object[] resobj = new object[]
268 { 268 {
269 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty, 269 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty,
270 rInfo.GetIntValue(), 270 rInfo.GetIntValue(),
271 rInfo.GetStrVal() 271 rInfo.GetStrVal()
272 }; 272 };
273 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 273 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
274 rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj 274 rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj
275 ); 275 );
276 } 276 }
277 } 277 }
278 } 278 }
279 279
280 public void CheckListeners() 280 public void CheckListeners()
281 { 281 {
282 if (m_ScriptEngine.World == null) 282 if (m_ScriptEngine.World == null)
283 return; 283 return;
284 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 284 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
285 285
286 while (comms.HasMessages()) 286 while (comms.HasMessages())
287 { 287 {
288 ListenerInfo lInfo = comms.GetNextMessage(); 288 ListenerInfo lInfo = comms.GetNextMessage();
289 289
290 //Deliver data to prim's listen handler 290 //Deliver data to prim's listen handler
291 object[] resobj = new object[] 291 object[] resobj = new object[]
292 { 292 {
293 lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() 293 lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
294 }; 294 };
295 295
296 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 296 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
297 lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj 297 lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj
298 ); 298 );
299 } 299 }
300 } 300 }
301 301
302 /// <summary> 302 /// <summary>
303 /// If set to true then threads and stuff should try to make a graceful exit 303 /// If set to true then threads and stuff should try to make a graceful exit
304 /// </summary> 304 /// </summary>
305 public bool PleaseShutdown 305 public bool PleaseShutdown
306 { 306 {
307 get { return _PleaseShutdown; } 307 get { return _PleaseShutdown; }
308 set { _PleaseShutdown = value; } 308 set { _PleaseShutdown = value; }
309 } 309 }
310 private bool _PleaseShutdown = false; 310 private bool _PleaseShutdown = false;
311 311
312 } 312 }
313} \ No newline at end of file 313} \ No newline at end of file