aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
diff options
context:
space:
mode:
authorMelanie Thielker2008-09-26 13:16:11 +0000
committerMelanie Thielker2008-09-26 13:16:11 +0000
commit824283ca3c2ab54868ed61fdb0a329221d69e5fa (patch)
tree9013892fa2afa579bffe8bdcd6a46e2242ed085c /OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
parent* Wind updates. Still random.. but in 4 directions instead of two! (diff)
downloadopensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.zip
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.gz
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.bz2
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.xz
Remove all the subclassing complexity and script server interfaces from
DNE and move all of DNE into the DotNetEngine directory. Remove references that would cause the script runtime to load the entire engine + scene into each script appdomain. This might help DNE memory consumption.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs381
1 files changed, 0 insertions, 381 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
deleted file mode 100644
index 7f52793..0000000
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
+++ /dev/null
@@ -1,381 +0,0 @@
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.Reflection;
31using System.Text.RegularExpressions;
32using System.Threading;
33using System.Globalization;
34using OpenMetaverse;
35using log4net;
36using OpenSim.Framework;
37using OpenSim.Region.Environment.Scenes.Scripting;
38
39namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
40{
41 /// <summary>
42 /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class
43 /// </summary>
44 public class EventQueueThreadClass : iScriptEngineFunctionModule
45 {
46 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// How many ms to sleep if queue is empty
50 /// </summary>
51 private static int nothingToDoSleepms;// = 50;
52 private static ThreadPriority MyThreadPriority;
53
54 public long LastExecutionStarted;
55 public bool InExecution = false;
56 public bool KillCurrentScript = false;
57
58 //private EventQueueManager eventQueueManager;
59 public Thread EventQueueThread;
60 private static int ThreadCount = 0;
61
62 private string ScriptEngineName = "ScriptEngine.Common";
63
64 public EventQueueThreadClass()//EventQueueManager eqm
65 {
66 //eventQueueManager = eqm;
67 ReadConfig();
68 Start();
69 }
70
71 ~EventQueueThreadClass()
72 {
73 Stop();
74 }
75
76 public void ReadConfig()
77 {
78 lock (ScriptEngine.ScriptEngines)
79 {
80 foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines)
81 {
82 ScriptEngineName = m_ScriptEngine.ScriptEngineName;
83 nothingToDoSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50);
84
85 // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually
86 string pri = m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal");
87 switch (pri.ToLower())
88 {
89 case "lowest":
90 MyThreadPriority = ThreadPriority.Lowest;
91 break;
92 case "belownormal":
93 MyThreadPriority = ThreadPriority.BelowNormal;
94 break;
95 case "normal":
96 MyThreadPriority = ThreadPriority.Normal;
97 break;
98 case "abovenormal":
99 MyThreadPriority = ThreadPriority.AboveNormal;
100 break;
101 case "highest":
102 MyThreadPriority = ThreadPriority.Highest;
103 break;
104 default:
105 MyThreadPriority = ThreadPriority.BelowNormal; // Default
106 m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri +
107 "\" in config file. Defaulting to \"BelowNormal\".");
108 break;
109 }
110 }
111 }
112 // Now set that priority
113 if (EventQueueThread != null)
114 if (EventQueueThread.IsAlive)
115 EventQueueThread.Priority = MyThreadPriority;
116 }
117
118 /// <summary>
119 /// Start thread
120 /// </summary>
121 private void Start()
122 {
123 EventQueueThread = new Thread(EventQueueThreadLoop);
124 EventQueueThread.IsBackground = true;
125
126 EventQueueThread.Priority = MyThreadPriority;
127 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
128 EventQueueThread.Start();
129 ThreadTracker.Add(EventQueueThread);
130
131 // Look at this... Don't you wish everyone did that solid coding everywhere? :P
132 if (ThreadCount == int.MaxValue)
133 ThreadCount = 0;
134 ThreadCount++;
135 }
136
137 public void Stop()
138 {
139 //PleaseShutdown = true; // Set shutdown flag
140 //Thread.Sleep(100); // Wait a bit
141 if (EventQueueThread != null && EventQueueThread.IsAlive == true)
142 {
143 try
144 {
145 EventQueueThread.Abort(); // Send abort
146 //EventQueueThread.Join(); // Wait for it
147 }
148 catch (Exception)
149 {
150 //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Exception killing worker thread: " + e.ToString());
151 }
152 }
153 }
154
155 private EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct();
156 private ScriptEngine lastScriptEngine;
157 /// <summary>
158 /// Queue processing thread loop
159 /// </summary>
160 private void EventQueueThreadLoop()
161 {
162 CultureInfo USCulture = new CultureInfo("en-US");
163 Thread.CurrentThread.CurrentCulture = USCulture;
164
165 //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread spawned");
166 try
167 {
168 while (true)
169 {
170 try
171 {
172 while (true)
173 {
174 DoProcessQueue();
175 }
176 }
177 catch (ThreadAbortException)
178 {
179 if (lastScriptEngine != null)
180 lastScriptEngine.Log.Info("[" + ScriptEngineName + "]: ThreadAbortException while executing function.");
181 }
182 catch (Exception e)
183 {
184 if (lastScriptEngine != null)
185 lastScriptEngine.Log.Error("[" + ScriptEngineName + "]: Exception in EventQueueThreadLoop: " + e.ToString());
186 }
187 }
188 }
189 catch (ThreadAbortException)
190 {
191 //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread killed: " + tae.Message);
192 }
193 }
194
195 public void DoProcessQueue()
196 {
197 //lock (ScriptEngine.ScriptEngines)
198 //{
199 foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
200 {
201 lastScriptEngine = m_ScriptEngine;
202 // Every now and then check if we should shut down
203 //if (PleaseShutdown || EventQueueManager.ThreadsToExit > 0)
204 //{
205 // // Someone should shut down, lets get exclusive lock
206 // lock (EventQueueManager.ThreadsToExitLock)
207 // {
208 // // Lets re-check in case someone grabbed it
209 // if (EventQueueManager.ThreadsToExit > 0)
210 // {
211 // // Its crowded here so we'll shut down
212 // EventQueueManager.ThreadsToExit--;
213 // Stop();
214 // return;
215 // }
216 // else
217 // {
218 // // We have been asked to shut down
219 // Stop();
220 // return;
221 // }
222 // }
223 //}
224
225 //try
226 // {
227 EventQueueManager.QueueItemStruct QIS = BlankQIS;
228 bool GotItem = false;
229
230 //if (PleaseShutdown)
231 // return;
232
233 if (m_ScriptEngine.m_EventQueueManager == null || m_ScriptEngine.m_EventQueueManager.eventQueue == null)
234 continue;
235
236 if (m_ScriptEngine.m_EventQueueManager.eventQueue.Count == 0)
237 {
238 // Nothing to do? Sleep a bit waiting for something to do
239 Thread.Sleep(nothingToDoSleepms);
240 }
241 else
242 {
243 // Something in queue, process
244 //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
245
246 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
247 lock (m_ScriptEngine.m_EventQueueManager.eventQueue)
248 {
249 GotItem = false;
250 for (int qc = 0; qc < m_ScriptEngine.m_EventQueueManager.eventQueue.Count; qc++)
251 {
252 // Get queue item
253 QIS = m_ScriptEngine.m_EventQueueManager.eventQueue.Dequeue();
254
255 // Check if object is being processed by someone else
256 if (m_ScriptEngine.m_EventQueueManager.TryLock(QIS.localID) == false)
257 {
258 // Object is already being processed, requeue it
259 m_ScriptEngine.m_EventQueueManager.eventQueue.Enqueue(QIS);
260 }
261 else
262 {
263 // We have lock on an object and can process it
264 GotItem = true;
265 break;
266 }
267 }
268 }
269
270 if (GotItem == true)
271 {
272 // Execute function
273 try
274 {
275 ///cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
276#if DEBUG
277 //eventQueueManager.m_ScriptEngine.Log.Debug("[" + ScriptEngineName + "]: " +
278 // "Executing event:\r\n"
279 // + "QIS.localID: " + QIS.localID
280 // + ", QIS.itemID: " + QIS.itemID
281 // + ", QIS.functionName: " +
282 // QIS.functionName);
283#endif
284 // Only pipe event if land supports it.
285 if (m_ScriptEngine.World.PipeEventsForScript(QIS.localID))
286 {
287 LastExecutionStarted = DateTime.Now.Ticks;
288 KillCurrentScript = false;
289 InExecution = true;
290 m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID,
291 QIS.itemID,
292 QIS.functionName,
293 QIS.llDetectParams,
294 QIS.param);
295 InExecution = false;
296 }
297 }
298 catch (Exception e)
299 {
300 InExecution = false;
301 // DISPLAY ERROR INWORLD
302 string text = "Error executing script function \"" + QIS.functionName +
303 "\":\r\n";
304 if (e.InnerException != null)
305 {
306 // Send inner exception
307 string line = " (unknown line)";
308 Regex rx = new Regex(@"SecondLife\.Script\..+[\s:](?<line>\d+)\.?\r?$", RegexOptions.Compiled);
309 if (rx.Match(e.InnerException.ToString()).Success)
310 line = " (line " + rx.Match(e.InnerException.ToString()).Result("${line}") + ")";
311 text += e.InnerException.Message.ToString() + line;
312 }
313 else
314 {
315 text += "\r\n";
316 // Send normal
317 text += e.Message.ToString();
318 }
319 if (KillCurrentScript)
320 text += "\r\nScript will be deactivated!";
321
322 try
323 {
324 if (text.Length > 1500)
325 text = text.Substring(0, 1500);
326 IScriptHost m_host =
327 m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
328 //if (m_host != null)
329 //{
330 m_ScriptEngine.World.SimChat(Utils.StringToBytes(text),
331 ChatTypeEnum.DebugChannel, 2147483647,
332 m_host.AbsolutePosition,
333 m_host.Name, m_host.UUID, false);
334 }
335 catch (Exception)
336 {
337 //}
338 //else
339 //{
340 // T oconsole
341 m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName +
342 "]: " +
343 "Unable to send text in-world:\r\n" +
344 text);
345 }
346 finally
347 {
348 // So we are done sending message in-world
349 if (KillCurrentScript)
350 {
351 m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript(
352 QIS.localID, QIS.itemID);
353 }
354 }
355
356 // Pass it on so it's displayed on the console
357 // and in the logs (mikem 2008.06.02).
358 throw e.InnerException;
359 }
360 finally
361 {
362 InExecution = false;
363 m_ScriptEngine.m_EventQueueManager.ReleaseLock(QIS.localID);
364 }
365 }
366 }
367 }
368 // }
369 }
370
371 ///// <summary>
372 ///// If set to true then threads and stuff should try to make a graceful exit
373 ///// </summary>
374 //public bool PleaseShutdown
375 //{
376 // get { return _PleaseShutdown; }
377 // set { _PleaseShutdown = value; }
378 //}
379 //private bool _PleaseShutdown = false;
380 }
381}