aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorTedd Hansen2008-02-01 23:36:36 +0000
committerTedd Hansen2008-02-01 23:36:36 +0000
commitd02a90823f2873f1b4de63062e3909d03a5a91fa (patch)
treecb0d8f79fd36bec98bbac39c1185ee40c75e7c6d
parentSCRIPT SUPPORT IS STILL BROKEN. (diff)
downloadopensim-SC_OLD-d02a90823f2873f1b4de63062e3909d03a5a91fa.zip
opensim-SC_OLD-d02a90823f2873f1b4de63062e3909d03a5a91fa.tar.gz
opensim-SC_OLD-d02a90823f2873f1b4de63062e3909d03a5a91fa.tar.bz2
opensim-SC_OLD-d02a90823f2873f1b4de63062e3909d03a5a91fa.tar.xz
SCRIPTING STILL BROKEN
Added comments and regions, restructured code Changed a lot of AppDomain junk from console from using Console.Write to Log.Verbose and set it to #if DEBUG All modules should now refresh their configuration runtime Made all logging in ScriptEngine.Common get script name from actual engine Renamed LSLLongCmdHandler to AsyncLSLCommandManager Added auto-recover with 5 sec throttle for new MaintenanceThread
-rw-r--r--OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs44
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs (renamed from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs)606
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs42
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs82
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs86
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs70
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs23
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs12
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs2
-rw-r--r--bin/OpenSim.ini.example21
17 files changed, 621 insertions, 404 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs
index dd46fa4..96a7dae 100644
--- a/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs
+++ b/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Region.ScriptEngine.Common
112 { 112 {
113 m_LSL_Functions = LSL_Functions; 113 m_LSL_Functions = LSL_Functions;
114 114
115 //MainLog.Instance.Notice("ScriptEngine", "LSL_BaseClass.Start() called."); 115 //MainLog.Instance.Notice(ScriptEngineName, "LSL_BaseClass.Start() called.");
116 116
117 // Get this AppDomain's settings and display some of them. 117 // Get this AppDomain's settings and display some of them.
118 AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation; 118 AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
index df049d8..bbf301d 100644
--- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Region.ScriptEngine.Common
61 m_localID = localID; 61 m_localID = localID;
62 m_itemID = itemID; 62 m_itemID = itemID;
63 63
64 //MainLog.Instance.Notice("ScriptEngine", "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]"); 64 //MainLog.Instance.Notice(ScriptEngineName, "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]");
65 } 65 }
66 66
67 private DateTime m_timer = DateTime.Now; 67 private DateTime m_timer = DateTime.Now;
@@ -1038,7 +1038,7 @@ namespace OpenSim.Region.ScriptEngine.Common
1038 public void llSetTimerEvent(double sec) 1038 public void llSetTimerEvent(double sec)
1039 { 1039 {
1040 // Setting timer repeat 1040 // Setting timer repeat
1041 m_ScriptEngine.m_LSLLongCmdHandler.SetTimerEvent(m_localID, m_itemID, sec); 1041 m_ScriptEngine.m_ASYNCLSLCommandManager.SetTimerEvent(m_localID, m_itemID, sec);
1042 } 1042 }
1043 1043
1044 public void llSleep(double sec) 1044 public void llSleep(double sec)
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
index 3519d54..2ed0529 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
@@ -35,7 +35,7 @@ using OpenSim.Region.ScriptEngine.Common;
35 35
36namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase 36namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
37{ 37{
38 public class AppDomainManager 38 public class AppDomainManager : iScriptEngineFunctionModule
39 { 39 {
40 40
41 // 41 //
@@ -85,12 +85,17 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
85 private object getLock = new object(); // Mutex 85 private object getLock = new object(); // Mutex
86 private object freeLock = new object(); // Mutex 86 private object freeLock = new object(); // Mutex
87 87
88 //private ScriptEngine m_scriptEngine; 88 private ScriptEngine m_scriptEngine;
89 //public AppDomainManager(ScriptEngine scriptEngine) 89 //public AppDomainManager(ScriptEngine scriptEngine)
90 public AppDomainManager(int MaxScriptsPerDomain) 90 public AppDomainManager(ScriptEngine scriptEngine)
91 { 91 {
92 maxScriptsPerAppDomain = MaxScriptsPerDomain; 92 m_scriptEngine = scriptEngine;
93 //m_scriptEngine = scriptEngine; 93 ReadConfig();
94 }
95
96 public void ReadConfig()
97 {
98 maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1);
94 } 99 }
95 100
96 /// <summary> 101 /// <summary>
@@ -99,7 +104,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
99 /// <returns>Free AppDomain</returns> 104 /// <returns>Free AppDomain</returns>
100 private AppDomainStructure GetFreeAppDomain() 105 private AppDomainStructure GetFreeAppDomain()
101 { 106 {
102 Console.WriteLine("Finding free AppDomain"); 107 // Console.WriteLine("Finding free AppDomain");
103 lock (getLock) 108 lock (getLock)
104 { 109 {
105 // Current full? 110 // Current full?
@@ -117,7 +122,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
117 currentAD.CurrentAppDomain = PrepareNewAppDomain(); 122 currentAD.CurrentAppDomain = PrepareNewAppDomain();
118 } 123 }
119 124
120 Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded); 125 // Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
121 return currentAD; 126 return currentAD;
122 } // lock 127 } // lock
123 } 128 }
@@ -144,7 +149,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
144 ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; 149 ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
145 150
146 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); 151 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
147 Console.WriteLine("Loading: " + 152 m_scriptEngine.Log.Verbose(m_scriptEngine.ScriptEngineName, "AppDomain Loading: " +
148 AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString()); 153 AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString());
149 AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll")); 154 AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll"));
150 155
@@ -169,17 +174,16 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
169 // Is number of unloaded bigger or equal to number of loaded? 174 // Is number of unloaded bigger or equal to number of loaded?
170 if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) 175 if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload)
171 { 176 {
172 Console.WriteLine("Found empty AppDomain, unloading");
173 // Remove from internal list 177 // Remove from internal list
174 appDomains.Remove(ads); 178 appDomains.Remove(ads);
175#if DEBUG 179#if DEBUG
180 Console.WriteLine("Found empty AppDomain, unloading");
176 long m = GC.GetTotalMemory(true); 181 long m = GC.GetTotalMemory(true);
177#endif 182#endif
178 // Unload 183 // Unload
179 AppDomain.Unload(ads.CurrentAppDomain); 184 AppDomain.Unload(ads.CurrentAppDomain);
180#if DEBUG 185#if DEBUG
181 Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + 186 m_scriptEngine.Log.Verbose(m_scriptEngine.ScriptEngineName, "AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory");
182 " bytes of memory");
183#endif 187#endif
184 } 188 }
185 } 189 }
@@ -193,7 +197,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
193 // Find next available AppDomain to put it in 197 // Find next available AppDomain to put it in
194 AppDomainStructure FreeAppDomain = GetFreeAppDomain(); 198 AppDomainStructure FreeAppDomain = GetFreeAppDomain();
195 199
196 Console.WriteLine("Loading into AppDomain: " + FileName); 200#if DEBUG
201 m_scriptEngine.Log.Verbose(m_scriptEngine.ScriptEngineName, "Loading into AppDomain: " + FileName);
202#endif
197 IScript mbrt = 203 IScript mbrt =
198 (IScript) 204 (IScript)
199 FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); 205 FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
@@ -213,7 +219,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
213 { 219 {
214 lock (freeLock) 220 lock (freeLock)
215 { 221 {
216 Console.WriteLine("Stopping script in AppDomain"); 222#if DEBUG
223 m_scriptEngine.Log.Verbose(m_scriptEngine.ScriptEngineName, "Stopping script in AppDomain");
224#endif
217 // Check if it is current AppDomain 225 // Check if it is current AppDomain
218 if (currentAD.CurrentAppDomain == ad) 226 if (currentAD.CurrentAppDomain == ad)
219 { 227 {
@@ -236,5 +244,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
236 244
237 UnloadAppDomains(); // Outsite lock, has its own GetLock 245 UnloadAppDomains(); // Outsite lock, has its own GetLock
238 } 246 }
247 /// <summary>
248 /// If set to true then threads and stuff should try to make a graceful exit
249 /// </summary>
250 public bool PleaseShutdown
251 {
252 get { return _PleaseShutdown; }
253 set { _PleaseShutdown = value; }
254 }
255 private bool _PleaseShutdown = false;
256
239 } 257 }
240} \ No newline at end of file 258} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
index 7d66638..5ec8f50 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
@@ -1,295 +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 LSLLongCmdHandler 41 public class AsyncLSLCommandManager : iScriptEngineFunctionModule
42 { 42 {
43 private Thread cmdHandlerThread; 43 private Thread cmdHandlerThread;
44 private int cmdHandlerThreadCycleSleepms = 100; 44 private int cmdHandlerThreadCycleSleepms;
45 45
46 private ScriptEngine m_ScriptEngine; 46 private ScriptEngine m_ScriptEngine;
47 47
48 public LSLLongCmdHandler(ScriptEngine _ScriptEngine) 48 public AsyncLSLCommandManager(ScriptEngine _ScriptEngine)
49 { 49 {
50 m_ScriptEngine = _ScriptEngine; 50 m_ScriptEngine = _ScriptEngine;
51 51 ReadConfig();
52 // Start the thread that will be doing the work 52
53 cmdHandlerThread = new Thread(CmdHandlerThreadLoop); 53 // Start the thread that will be doing the work
54 cmdHandlerThread.Name = "CmdHandlerThread"; 54 cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
55 cmdHandlerThread.Priority = ThreadPriority.BelowNormal; 55 cmdHandlerThread.Name = "CmdHandlerThread";
56 cmdHandlerThread.IsBackground = true; 56 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
57 cmdHandlerThread.Start(); 57 cmdHandlerThread.IsBackground = true;
58 } 58 cmdHandlerThread.Start();
59 59 }
60 ~LSLLongCmdHandler() 60
61 { 61 public void ReadConfig()
62 // Shut down thread 62 {
63 try 63 cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 50);
64 { 64 }
65 if (cmdHandlerThread != null) 65
66 { 66
67 if (cmdHandlerThread.IsAlive == true) 67 ~AsyncLSLCommandManager()
68 { 68 {
69 cmdHandlerThread.Abort(); 69 // Shut down thread
70 cmdHandlerThread.Join(); 70 try
71 } 71 {
72 } 72 if (cmdHandlerThread != null)
73 } 73 {
74 catch 74 if (cmdHandlerThread.IsAlive == true)
75 { 75 {
76 } 76 cmdHandlerThread.Abort();
77 } 77 cmdHandlerThread.Join();
78 78 }
79 private void CmdHandlerThreadLoop() 79 }
80 { 80 }
81 while (true) 81 catch
82 { 82 {
83 // Check timers 83 }
84 CheckTimerEvents(); 84 }
85 Thread.Sleep(25); 85
86 // Check HttpRequests 86 private void CmdHandlerThreadLoop()
87 CheckHttpRequests(); 87 {
88 Thread.Sleep(25); 88 while (true)
89 // Check XMLRPCRequests 89 {
90 CheckXMLRPCRequests(); 90 // Check timers
91 Thread.Sleep(25); 91 CheckTimerEvents();
92 // Check Listeners 92 Thread.Sleep(25);
93 CheckListeners(); 93 // Check HttpRequests
94 Thread.Sleep(25); 94 CheckHttpRequests();
95 95 Thread.Sleep(25);
96 // Sleep before next cycle 96 // Check XMLRPCRequests
97 //Thread.Sleep(cmdHandlerThreadCycleSleepms); 97 CheckXMLRPCRequests();
98 } 98 Thread.Sleep(25);
99 } 99 // Check Listeners
100 100 CheckListeners();
101 /// <summary> 101 Thread.Sleep(25);
102 /// Remove a specific script (and all its pending commands) 102
103 /// </summary> 103 // Sleep before next cycle
104 /// <param name="m_localID"></param> 104 //Thread.Sleep(cmdHandlerThreadCycleSleepms);
105 /// <param name="m_itemID"></param> 105 }
106 public void RemoveScript(uint localID, LLUUID itemID) 106 }
107 { 107
108 // Remove a specific script 108 /// <summary>
109 109 /// Remove a specific script (and all its pending commands)
110 // Remove from: Timers 110 /// </summary>
111 UnSetTimerEvents(localID, itemID); 111 /// <param name="m_localID"></param>
112 // Remove from: HttpRequest 112 /// <param name="m_itemID"></param>
113 IHttpRequests iHttpReq = 113 public void RemoveScript(uint localID, LLUUID itemID)
114 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>(); 114 {
115 iHttpReq.StopHttpRequest(localID, itemID); 115 // Remove a specific script
116 } 116
117 117 // Remove from: Timers
118 #region TIMER 118 UnSetTimerEvents(localID, itemID);
119 119 // Remove from: HttpRequest
120 // 120 IHttpRequests iHttpReq =
121 // TIMER 121 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
122 // 122 iHttpReq.StopHttpRequest(localID, itemID);
123 private class TimerClass 123 }
124 { 124
125 public uint localID; 125 #region TIMER
126 public LLUUID itemID; 126
127 public double interval; 127 //
128 public DateTime next; 128 // TIMER
129 } 129 //
130 130 private class TimerClass
131 private List<TimerClass> Timers = new List<TimerClass>(); 131 {
132 private object TimerListLock = new object(); 132 public uint localID;
133 133 public LLUUID itemID;
134 public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec) 134 public double interval;
135 { 135 public DateTime next;
136 Console.WriteLine("SetTimerEvent"); 136 }
137 137
138 // Always remove first, in case this is a re-set 138 private List<TimerClass> Timers = new List<TimerClass>();
139 UnSetTimerEvents(m_localID, m_itemID); 139 private object TimerListLock = new object();
140 if (sec == 0) // Disabling timer 140
141 return; 141 public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
142 142 {
143 // Add to timer 143 Console.WriteLine("SetTimerEvent");
144 TimerClass ts = new TimerClass(); 144
145 ts.localID = m_localID; 145 // Always remove first, in case this is a re-set
146 ts.itemID = m_itemID; 146 UnSetTimerEvents(m_localID, m_itemID);
147 ts.interval = sec; 147 if (sec == 0) // Disabling timer
148 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 148 return;
149 lock (TimerListLock) 149
150 { 150 // Add to timer
151 Timers.Add(ts); 151 TimerClass ts = new TimerClass();
152 } 152 ts.localID = m_localID;
153 } 153 ts.itemID = m_itemID;
154 154 ts.interval = sec;
155 public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID) 155 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
156 { 156 lock (TimerListLock)
157 // Remove from timer 157 {
158 lock (TimerListLock) 158 Timers.Add(ts);
159 { 159 }
160 List<TimerClass> NewTimers = new List<TimerClass>(); 160 }
161 foreach (TimerClass ts in Timers) 161
162 { 162 public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
163 if (ts.localID != m_localID && ts.itemID != m_itemID) 163 {
164 { 164 // Remove from timer
165 NewTimers.Add(ts); 165 lock (TimerListLock)
166 } 166 {
167 } 167 List<TimerClass> NewTimers = new List<TimerClass>();
168 Timers.Clear(); 168 foreach (TimerClass ts in Timers)
169 Timers = NewTimers; 169 {
170 } 170 if (ts.localID != m_localID && ts.itemID != m_itemID)
171 } 171 {
172 172 NewTimers.Add(ts);
173 public void CheckTimerEvents() 173 }
174 { 174 }
175 // Nothing to do here? 175 Timers.Clear();
176 if (Timers.Count == 0) 176 Timers = NewTimers;
177 return; 177 }
178 178 }
179 lock (TimerListLock) 179
180 { 180 public void CheckTimerEvents()
181 // Go through all timers 181 {
182 foreach (TimerClass ts in Timers) 182 // Nothing to do here?
183 { 183 if (Timers.Count == 0)
184 // Time has passed? 184 return;
185 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) 185
186 { 186 lock (TimerListLock)
187 // Add it to queue 187 {
188 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull, 188 // Go through all timers
189 new object[] {}); 189 foreach (TimerClass ts in Timers)
190 // set next interval 190 {
191 191 // Time has passed?
192 192 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
193 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 193 {
194 } 194 // Add it to queue
195 } 195 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull,
196 } // lock 196 new object[] {});
197 } 197 // set next interval
198 198
199 #endregion 199
200 200 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
201 #region HTTP REQUEST 201 }
202 202 }
203 public void CheckHttpRequests() 203 } // lock
204 { 204 }
205 if (m_ScriptEngine.World == null) 205
206 return; 206 #endregion
207 207
208 IHttpRequests iHttpReq = 208 #region HTTP REQUEST
209 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>(); 209
210 210 public void CheckHttpRequests()
211 HttpRequestClass httpInfo = null; 211 {
212 212 if (m_ScriptEngine.World == null)
213 if (iHttpReq != null) 213 return;
214 httpInfo = iHttpReq.GetNextCompletedRequest(); 214
215 215 IHttpRequests iHttpReq =
216 while (httpInfo != null) 216 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
217 { 217
218 //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status); 218 HttpRequestClass httpInfo = null;
219 219
220 // Deliver data to prim's remote_data handler 220 if (iHttpReq != null)
221 // 221 httpInfo = iHttpReq.GetNextCompletedRequest();
222 // TODO: Returning null for metadata, since the lsl function 222
223 // only returns the byte for HTTP_BODY_TRUNCATED, which is not 223 while (httpInfo != null)
224 // implemented here yet anyway. Should be fixed if/when maxsize 224 {
225 // is supported 225 //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status);
226 226
227 object[] resobj = new object[] 227 // Deliver data to prim's remote_data handler
228 { 228 //
229 httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body 229 // TODO: Returning null for metadata, since the lsl function
230 }; 230 // only returns the byte for HTTP_BODY_TRUNCATED, which is not
231 231 // implemented here yet anyway. Should be fixed if/when maxsize
232 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 232 // is supported
233 httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj 233
234 ); 234 object[] resobj = new object[]
235 235 {
236 httpInfo.Stop(); 236 httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
237 httpInfo = null; 237 };
238 238
239 httpInfo = iHttpReq.GetNextCompletedRequest(); 239 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
240 } 240 httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj
241 } 241 );
242 242
243 #endregion 243 httpInfo.Stop();
244 244 httpInfo = null;
245 public void CheckXMLRPCRequests() 245
246 { 246 httpInfo = iHttpReq.GetNextCompletedRequest();
247 if (m_ScriptEngine.World == null) 247 }
248 return; 248 }
249 249
250 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 250 #endregion
251 251
252 if (xmlrpc != null) 252 public void CheckXMLRPCRequests()
253 { 253 {
254 while (xmlrpc.hasRequests()) 254 if (m_ScriptEngine.World == null)
255 { 255 return;
256 RPCRequestInfo rInfo = xmlrpc.GetNextRequest(); 256
257 //Console.WriteLine("PICKED REQUEST"); 257 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
258 258
259 //Deliver data to prim's remote_data handler 259 if (xmlrpc != null)
260 object[] resobj = new object[] 260 {
261 { 261 while (xmlrpc.hasRequests())
262 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty, 262 {
263 rInfo.GetIntValue(), 263 RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
264 rInfo.GetStrVal() 264 //Console.WriteLine("PICKED REQUEST");
265 }; 265
266 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 266 //Deliver data to prim's remote_data handler
267 rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj 267 object[] resobj = new object[]
268 ); 268 {
269 } 269 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty,
270 } 270 rInfo.GetIntValue(),
271 } 271 rInfo.GetStrVal()
272 272 };
273 public void CheckListeners() 273 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
274 { 274 rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj
275 if (m_ScriptEngine.World == null) 275 );
276 return; 276 }
277 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 277 }
278 278 }
279 while (comms.HasMessages()) 279
280 { 280 public void CheckListeners()
281 ListenerInfo lInfo = comms.GetNextMessage(); 281 {
282 282 if (m_ScriptEngine.World == null)
283 //Deliver data to prim's listen handler 283 return;
284 object[] resobj = new object[] 284 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
285 { 285
286 lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() 286 while (comms.HasMessages())
287 }; 287 {
288 288 ListenerInfo lInfo = comms.GetNextMessage();
289 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 289
290 lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj 290 //Deliver data to prim's listen handler
291 ); 291 object[] resobj = new object[]
292 } 292 {
293 } 293 lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
294 } 294 };
295
296 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
297 lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj
298 );
299 }
300 }
301
302 /// <summary>
303 /// If set to true then threads and stuff should try to make a graceful exit
304 /// </summary>
305 public bool PleaseShutdown
306 {
307 get { return _PleaseShutdown; }
308 set { _PleaseShutdown = value; }
309 }
310 private bool _PleaseShutdown = false;
311
312 }
295} \ No newline at end of file 313} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs
index bce26ff..fe6dfcd 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs
@@ -44,14 +44,14 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
44 public static void SendToDebug(string Message) 44 public static void SendToDebug(string Message)
45 { 45 {
46 //if (Debug == true) 46 //if (Debug == true)
47 mySE.Log.Verbose("ScriptEngine", "Debug: " + Message); 47 mySE.Log.Verbose(mySE.ScriptEngineName, "Debug: " + Message);
48 //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); 48 //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
49 } 49 }
50 50
51 public static void SendToLog(string Message) 51 public static void SendToLog(string Message)
52 { 52 {
53 //if (Debug == true) 53 //if (Debug == true)
54 mySE.Log.Verbose("ScriptEngine", "LOG: " + Message); 54 mySE.Log.Verbose(mySE.ScriptEngineName, "LOG: " + Message);
55 //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); 55 //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
56 } 56 }
57 } 57 }
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
index 250a5df..678c3d0 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
37 /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. 37 /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
38 /// </summary> 38 /// </summary>
39 [Serializable] 39 [Serializable]
40 public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents 40 public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents, iScriptEngineFunctionModule
41 { 41 {
42 42
43 // 43 //
@@ -59,12 +59,13 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
59 public EventManager(ScriptEngine _ScriptEngine, bool performHookUp) 59 public EventManager(ScriptEngine _ScriptEngine, bool performHookUp)
60 { 60 {
61 myScriptEngine = _ScriptEngine; 61 myScriptEngine = _ScriptEngine;
62 ReadConfig();
62 63
63 // Hook up to events from OpenSim 64 // Hook up to events from OpenSim
64 // We may not want to do it because someone is controlling us and will deliver events to us 65 // We may not want to do it because someone is controlling us and will deliver events to us
65 if (performHookUp) 66 if (performHookUp)
66 { 67 {
67 myScriptEngine.Log.Verbose("ScriptEngine", "Hooking up to server events"); 68 myScriptEngine.Log.Verbose(myScriptEngine.ScriptEngineName, "Hooking up to server events");
68 myScriptEngine.World.EventManager.OnObjectGrab += touch_start; 69 myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
69 myScriptEngine.World.EventManager.OnRezScript += OnRezScript; 70 myScriptEngine.World.EventManager.OnRezScript += OnRezScript;
70 myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; 71 myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript;
@@ -73,6 +74,11 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
73 } 74 }
74 } 75 }
75 76
77 public void ReadConfig()
78 {
79 }
80
81
76 public void changed(uint localID, uint change) 82 public void changed(uint localID, uint change)
77 { 83 {
78 // Add to queue for all scripts in localID, Object pass change. 84 // Add to queue for all scripts in localID, Object pass change.
@@ -263,5 +269,16 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
263 { 269 {
264 // myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "http_response", EventQueueManager.llDetectNull); 270 // myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "http_response", EventQueueManager.llDetectNull);
265 } 271 }
272
273 /// <summary>
274 /// If set to true then threads and stuff should try to make a graceful exit
275 /// </summary>
276 public bool PleaseShutdown
277 {
278 get { return _PleaseShutdown; }
279 set { _PleaseShutdown = value; }
280 }
281 private bool _PleaseShutdown = false;
282
266 } 283 }
267} \ No newline at end of file 284} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
index 04c084a..3ba4618 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
42 /// Events are queued and executed in separate thread 42 /// Events are queued and executed in separate thread
43 /// </summary> 43 /// </summary>
44 [Serializable] 44 [Serializable]
45 public class EventQueueManager 45 public class EventQueueManager : iScriptEngineFunctionModule
46 { 46 {
47 47
48 // 48 //
@@ -197,13 +197,22 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
197 197
198 } 198 }
199 199
200 private void ReadConfig() 200 public void ReadConfig()
201 { 201 {
202 // Refresh config
202 numberOfThreads = m_ScriptEngine.ScriptConfigSource.GetInt("NumberOfScriptThreads", 2); 203 numberOfThreads = m_ScriptEngine.ScriptConfigSource.GetInt("NumberOfScriptThreads", 2);
203 maxFunctionExecutionTimems = m_ScriptEngine.ScriptConfigSource.GetInt("MaxEventExecutionTimeMs", 5000); 204 maxFunctionExecutionTimems = m_ScriptEngine.ScriptConfigSource.GetInt("MaxEventExecutionTimeMs", 5000);
204 EnforceMaxExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("EnforceMaxEventExecutionTime", false); 205 EnforceMaxExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("EnforceMaxEventExecutionTime", false);
205 KillScriptOnMaxFunctionExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("DeactivateScriptOnTimeout", false); 206 KillScriptOnMaxFunctionExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("DeactivateScriptOnTimeout", false);
206 207
208 // Now refresh config in all threads
209 lock (eventQueueThreadsLock)
210 {
211 foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads)
212 {
213 EventQueueThread.ReadConfig();
214 }
215 }
207 } 216 }
208 217
209 #endregion 218 #endregion
@@ -222,7 +231,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
222 { 231 {
223 foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads) 232 foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads)
224 { 233 {
225 EventQueueThread.Shutdown(); 234 AbortThreadClass(EventQueueThread);
226 } 235 }
227 eventQueueThreads.Clear(); 236 eventQueueThreads.Clear();
228 staticGlobalEventQueueThreads.Clear(); 237 staticGlobalEventQueueThreads.Clear();
@@ -243,7 +252,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
243 EventQueueThreadClass eqtc = new EventQueueThreadClass(this); 252 EventQueueThreadClass eqtc = new EventQueueThreadClass(this);
244 eventQueueThreads.Add(eqtc); 253 eventQueueThreads.Add(eqtc);
245 staticGlobalEventQueueThreads.Add(eqtc); 254 staticGlobalEventQueueThreads.Add(eqtc);
246 m_ScriptEngine.Log.Debug("DotNetEngine", "Started new script execution thread. Current thread count: " + eventQueueThreads.Count); 255 m_ScriptEngine.Log.Debug(m_ScriptEngine.ScriptEngineName, "Started new script execution thread. Current thread count: " + eventQueueThreads.Count);
247 256
248 } 257 }
249 private void AbortThreadClass(EventQueueThreadClass threadClass) 258 private void AbortThreadClass(EventQueueThreadClass threadClass)
@@ -252,16 +261,17 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
252 eventQueueThreads.Remove(threadClass); 261 eventQueueThreads.Remove(threadClass);
253 if (staticGlobalEventQueueThreads.Contains(threadClass)) 262 if (staticGlobalEventQueueThreads.Contains(threadClass))
254 staticGlobalEventQueueThreads.Remove(threadClass); 263 staticGlobalEventQueueThreads.Remove(threadClass);
264
255 try 265 try
256 { 266 {
257 threadClass.Shutdown(); 267 threadClass.Stop();
258 } 268 }
259 catch (Exception ex) 269 catch (Exception ex)
260 { 270 {
261 m_ScriptEngine.Log.Error("EventQueueManager", "If you see this, could you please report it to Tedd:"); 271 m_ScriptEngine.Log.Error(m_ScriptEngine.ScriptEngineName + ":EventQueueManager", "If you see this, could you please report it to Tedd:");
262 m_ScriptEngine.Log.Error("EventQueueManager", "Script thread execution timeout kill ended in exception: " + ex.ToString()); 272 m_ScriptEngine.Log.Error(m_ScriptEngine.ScriptEngineName + ":EventQueueManager", "Script thread execution timeout kill ended in exception: " + ex.ToString());
263 } 273 }
264 m_ScriptEngine.Log.Debug("DotNetEngine", "Killed script execution thread. Remaining thread count: " + eventQueueThreads.Count); 274 m_ScriptEngine.Log.Debug(m_ScriptEngine.ScriptEngineName, "Killed script execution thread. Remaining thread count: " + eventQueueThreads.Count);
265 } 275 }
266 #endregion 276 #endregion
267 277
@@ -313,7 +323,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
313 public void AddToObjectQueue(uint localID, string FunctionName, Queue_llDetectParams_Struct qParams, params object[] param) 323 public void AddToObjectQueue(uint localID, string FunctionName, Queue_llDetectParams_Struct qParams, params object[] param)
314 { 324 {
315 // Determine all scripts in Object and add to their queue 325 // Determine all scripts in Object and add to their queue
316 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName); 326 //myScriptEngine.m_logger.Verbose(ScriptEngineName, "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName);
317 327
318 328
319 // Do we have any scripts in this object at all? If not, return 329 // Do we have any scripts in this object at all? If not, return
@@ -367,6 +377,10 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
367 /// </summary> 377 /// </summary>
368 public void AdjustNumberOfScriptThreads() 378 public void AdjustNumberOfScriptThreads()
369 { 379 {
380 // Is there anything here for us to do?
381 if (eventQueueThreads.Count == numberOfThreads)
382 return;
383
370 lock (eventQueueThreadsLock) 384 lock (eventQueueThreadsLock)
371 { 385 {
372 int diff = numberOfThreads - eventQueueThreads.Count; 386 int diff = numberOfThreads - eventQueueThreads.Count;
@@ -424,5 +438,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
424 } 438 }
425 } 439 }
426 #endregion 440 #endregion
441 /// <summary>
442 /// If set to true then threads and stuff should try to make a graceful exit
443 /// </summary>
444 public bool PleaseShutdown
445 {
446 get { return _PleaseShutdown; }
447 set { _PleaseShutdown = value; }
448 }
449 private bool _PleaseShutdown = false;
450
427 } 451 }
428} \ No newline at end of file 452} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
index e610c36..c19d641 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
@@ -12,12 +12,13 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
12 /// <summary> 12 /// <summary>
13 /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class 13 /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class
14 /// </summary> 14 /// </summary>
15 public class EventQueueThreadClass 15 public class EventQueueThreadClass: iScriptEngineFunctionModule
16 { 16 {
17 /// <summary> 17 /// <summary>
18 /// How many ms to sleep if queue is empty 18 /// How many ms to sleep if queue is empty
19 /// </summary> 19 /// </summary>
20 private int nothingToDoSleepms;// = 50; 20 private int nothingToDoSleepms;// = 50;
21 private ThreadPriority MyThreadPriority;
21 22
22 public long LastExecutionStarted; 23 public long LastExecutionStarted;
23 public bool InExecution = false; 24 public bool InExecution = false;
@@ -26,25 +27,27 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
26 private EventQueueManager eventQueueManager; 27 private EventQueueManager eventQueueManager;
27 public Thread EventQueueThread; 28 public Thread EventQueueThread;
28 private static int ThreadCount = 0; 29 private static int ThreadCount = 0;
29 private ThreadPriority MyThreadPriority; 30
31 private string ScriptEngineName = "ScriptEngine.Common";
30 32
31 public EventQueueThreadClass(EventQueueManager eqm) 33 public EventQueueThreadClass(EventQueueManager eqm)
32 { 34 {
33 eventQueueManager = eqm; 35 eventQueueManager = eqm;
34 nothingToDoSleepms = eqm.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50); 36 ReadConfig();
35 Start(); 37 Start();
36 } 38 }
37 39
38 ~EventQueueThreadClass() 40 ~EventQueueThreadClass()
39 { 41 {
40 Shutdown(); 42 Stop();
41 } 43 }
42 44
43 /// <summary> 45
44 /// Start thread 46 public void ReadConfig()
45 /// </summary>
46 private void Start()
47 { 47 {
48 ScriptEngineName = eventQueueManager.m_ScriptEngine.ScriptEngineName;
49 nothingToDoSleepms = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50);
50
48 // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually 51 // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually
49 string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal"); 52 string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal");
50 switch (pri.ToLower()) 53 switch (pri.ToLower())
@@ -70,6 +73,19 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
70 break; 73 break;
71 } 74 }
72 75
76 // Now set that priority
77 if (EventQueueThread != null)
78 if (EventQueueThread.IsAlive)
79 EventQueueThread.Priority = MyThreadPriority;
80
81 }
82
83
84 /// <summary>
85 /// Start thread
86 /// </summary>
87 private void Start()
88 {
73 89
74 EventQueueThread = new Thread(EventQueueThreadLoop); 90 EventQueueThread = new Thread(EventQueueThreadLoop);
75 EventQueueThread.IsBackground = true; 91 EventQueueThread.IsBackground = true;
@@ -84,18 +100,20 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
84 ThreadCount++; 100 ThreadCount++;
85 } 101 }
86 102
87 public void Shutdown() 103 public void Stop()
88 { 104 {
105 PleaseShutdown = true; // Set shutdown flag
106 Thread.Sleep(100); // Wait a bit
89 if (EventQueueThread != null && EventQueueThread.IsAlive == true) 107 if (EventQueueThread != null && EventQueueThread.IsAlive == true)
90 { 108 {
91 try 109 try
92 { 110 {
93 EventQueueThread.Abort(); 111 EventQueueThread.Abort(); // Send abort
94 EventQueueThread.Join(); 112 EventQueueThread.Join(); // Wait for it
95 } 113 }
96 catch (Exception) 114 catch (Exception)
97 { 115 {
98 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString()); 116 //myScriptEngine.Log.Verbose(ScriptEngineName, "EventQueueManager Exception killing worker thread: " + e.ToString());
99 } 117 }
100 } 118 }
101 } 119 }
@@ -106,10 +124,10 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
106 /// </summary> 124 /// </summary>
107 private void EventQueueThreadLoop() 125 private void EventQueueThreadLoop()
108 { 126 {
109 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned"); 127 //myScriptEngine.m_logger.Verbose(ScriptEngineName, "EventQueueManager Worker thread spawned");
110 try 128 try
111 { 129 {
112 while (true) 130 while (true)
113 { 131 {
114 try 132 try
115 { 133 {
@@ -117,7 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
117 while (true) 135 while (true)
118 { 136 {
119 // Every now and then check if we should shut down 137 // Every now and then check if we should shut down
120 if (eventQueueManager.ThreadsToExit > 0) 138 if (PleaseShutdown || eventQueueManager.ThreadsToExit > 0)
121 { 139 {
122 // Someone should shut down, lets get exclusive lock 140 // Someone should shut down, lets get exclusive lock
123 lock (eventQueueManager.ThreadsToExitLock) 141 lock (eventQueueManager.ThreadsToExitLock)
@@ -125,9 +143,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
125 // Lets re-check in case someone grabbed it 143 // Lets re-check in case someone grabbed it
126 if (eventQueueManager.ThreadsToExit > 0) 144 if (eventQueueManager.ThreadsToExit > 0)
127 { 145 {
128 // We are go for shutdown 146 // Its crowded here so we'll shut down
129 eventQueueManager.ThreadsToExit--; 147 eventQueueManager.ThreadsToExit--;
130 Shutdown(); 148 Stop();
149 return;
150 }
151 else
152 {
153 // We have been asked to shut down
154 Stop();
131 return; 155 return;
132 } 156 }
133 } 157 }
@@ -139,6 +163,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
139 EventQueueManager.QueueItemStruct QIS = BlankQIS; 163 EventQueueManager.QueueItemStruct QIS = BlankQIS;
140 bool GotItem = false; 164 bool GotItem = false;
141 165
166 if (PleaseShutdown)
167 return;
168
142 if (eventQueueManager.eventQueue.Count == 0) 169 if (eventQueueManager.eventQueue.Count == 0)
143 { 170 {
144 // Nothing to do? Sleep a bit waiting for something to do 171 // Nothing to do? Sleep a bit waiting for something to do
@@ -147,7 +174,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
147 else 174 else
148 { 175 {
149 // Something in queue, process 176 // Something in queue, process
150 //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); 177 //myScriptEngine.m_logger.Verbose(ScriptEngineName, "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
151 178
152 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD 179 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
153 lock (eventQueueManager.queueLock) 180 lock (eventQueueManager.queueLock)
@@ -179,7 +206,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
179 try 206 try
180 { 207 {
181#if DEBUG 208#if DEBUG
182 eventQueueManager.m_ScriptEngine.Log.Debug("ScriptEngine", 209 eventQueueManager.m_ScriptEngine.Log.Debug(ScriptEngineName,
183 "Executing event:\r\n" 210 "Executing event:\r\n"
184 + "QIS.localID: " + QIS.localID 211 + "QIS.localID: " + QIS.localID
185 + ", QIS.itemID: " + QIS.itemID 212 + ", QIS.itemID: " + QIS.itemID
@@ -235,7 +262,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
235 //else 262 //else
236 //{ 263 //{
237 // T oconsole 264 // T oconsole
238 eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngine", 265 eventQueueManager.m_ScriptEngine.Log.Error(ScriptEngineName,
239 "Unable to send text in-world:\r\n" + 266 "Unable to send text in-world:\r\n" +
240 text); 267 text);
241 } 268 }
@@ -260,19 +287,28 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
260 } 287 }
261 catch (ThreadAbortException tae) 288 catch (ThreadAbortException tae)
262 { 289 {
263 eventQueueManager.m_ScriptEngine.Log.Notice("ScriptEngine", "ThreadAbortException while executing function."); 290 eventQueueManager.m_ScriptEngine.Log.Notice(ScriptEngineName, "ThreadAbortException while executing function.");
264 } 291 }
265 catch (Exception e) 292 catch (Exception e)
266 { 293 {
267 eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString()); 294 eventQueueManager.m_ScriptEngine.Log.Error(ScriptEngineName, "Exception in EventQueueThreadLoop: " + e.ToString());
268 } 295 }
269 } // while 296 } // while
270 } // try 297 } // try
271 catch (ThreadAbortException) 298 catch (ThreadAbortException)
272 { 299 {
273 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message); 300 //myScriptEngine.Log.Verbose(ScriptEngineName, "EventQueueManager Worker thread killed: " + tae.Message);
274 } 301 }
275 } 302 }
276 303
304 /// <summary>
305 /// If set to true then threads and stuff should try to make a graceful exit
306 /// </summary>
307 public bool PleaseShutdown
308 {
309 get { return _PleaseShutdown; }
310 set { _PleaseShutdown = value; }
311 }
312 private bool _PleaseShutdown = false;
277 } 313 }
278} 314}
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs
index 9536291..105d47f 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs
@@ -8,7 +8,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
8 /// <summary> 8 /// <summary>
9 /// This class does maintenance on script engine. 9 /// This class does maintenance on script engine.
10 /// </summary> 10 /// </summary>
11 public class MaintenanceThread 11 public class MaintenanceThread : iScriptEngineFunctionModule
12 { 12 {
13 public ScriptEngine m_ScriptEngine; 13 public ScriptEngine m_ScriptEngine;
14 private int MaintenanceLoopms; 14 private int MaintenanceLoopms;
@@ -28,7 +28,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
28 StopMaintenanceThread(); 28 StopMaintenanceThread();
29 } 29 }
30 30
31 private void ReadConfig() 31 public void ReadConfig()
32 { 32 {
33 MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50); 33 MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50);
34 } 34 }
@@ -80,48 +80,74 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
80 /// </summary> 80 /// </summary>
81 public void MaintenanceLoop() 81 public void MaintenanceLoop()
82 { 82 {
83 try 83 if (m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens < MaintenanceLoopms)
84 m_ScriptEngine.Log.Warn(m_ScriptEngine.ScriptEngineName,
85 "Configuration error: MaxEventExecutionTimeMs is less than MaintenanceLoopms. The Maintenance Loop will only check scripts once per run.");
86
87 while (true)
84 { 88 {
85 long Last_maxFunctionExecutionTimens = 0;// DateTime.Now.Ticks; 89 try
86 long Last_ReReadConfigFilens = DateTime.Now.Ticks;
87 while (true)
88 { 90 {
89 System.Threading.Thread.Sleep(MaintenanceLoopms); // Sleep 91 long Last_maxFunctionExecutionTimens = 0; // DateTime.Now.Ticks;
90 92 long Last_ReReadConfigFilens = DateTime.Now.Ticks;
91 // Re-reading config every x seconds? 93 while (true)
92 if (m_ScriptEngine.ReReadConfigFileSeconds > 0)
93 { 94 {
94 // Check if its time to re-read config 95 System.Threading.Thread.Sleep(MaintenanceLoopms); // Sleep before next pass
95 if (DateTime.Now.Ticks - Last_ReReadConfigFilens > m_ScriptEngine.ReReadConfigFilens) 96 if (PleaseShutdown)
97 return;
98 //
99 // Re-reading config every x seconds
100 //
101 if (m_ScriptEngine.RefreshConfigFileSeconds > 0)
96 { 102 {
97 // Its time to re-read config file 103 // Check if its time to re-read config
98 m_ScriptEngine.ConfigSource.Reload(); // Re-read config 104 if (DateTime.Now.Ticks - Last_ReReadConfigFilens > m_ScriptEngine.RefreshConfigFilens)
99 Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time 105 {
106 // Its time to re-read config file
107 m_ScriptEngine.ConfigSource.Reload(); // Refresh config
108 m_ScriptEngine.ReadConfig();
109 Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
110 }
100 } 111 }
101 }
102 112
103 // Adjust number of running script threads if not correct 113 //
104 if (m_ScriptEngine.m_EventQueueManager.eventQueueThreads.Count != m_ScriptEngine.m_EventQueueManager.numberOfThreads) 114 // Adjust number of running script threads if not correct
105 { 115 //
106 m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads(); 116 m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
107 }
108
109 117
110 // Check if any script has exceeded its max execution time 118 //
111 if (m_ScriptEngine.m_EventQueueManager.EnforceMaxExecutionTime) 119 // Check if any script has exceeded its max execution time
112 { 120 //
113 if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens > m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens) 121 if (m_ScriptEngine.m_EventQueueManager.EnforceMaxExecutionTime)
114 { 122 {
115 m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check 123 // We are enforcing execution time
116 Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time 124 if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
125 m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens)
126 {
127 // Its time to check again
128 m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
129 Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
130 }
117 } 131 }
118 } 132 }
119 } 133 }
120 } 134 catch (Exception ex)
121 catch (ThreadAbortException tae) 135 {
122 { 136 m_ScriptEngine.Log.Error(m_ScriptEngine.ScriptEngineName, "Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: " + ex.ToString());
137 Thread.Sleep(5000);
138 }
123 } 139 }
124 } 140 }
125 #endregion 141 #endregion
142 /// <summary>
143 /// If set to true then threads and stuff should try to make a graceful exit
144 /// </summary>
145 public bool PleaseShutdown
146 {
147 get { return _PleaseShutdown; }
148 set { _PleaseShutdown = value; }
149 }
150 private bool _PleaseShutdown = false;
151
126 } 152 }
127} 153}
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
index cfcc36e..c237282 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
@@ -42,27 +42,28 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
42 /// </summary> 42 /// </summary>
43 /// 43 ///
44 [Serializable] 44 [Serializable]
45 public abstract class ScriptEngine : IRegionModule, OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.ScriptEngine 45 public abstract class ScriptEngine : IRegionModule, OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.ScriptEngine, iScriptEngineFunctionModule
46 { 46 {
47 public Scene World; 47 public Scene World;
48 public EventManager m_EventManager; // Handles and queues incoming events from OpenSim 48 public EventManager m_EventManager; // Handles and queues incoming events from OpenSim
49 public EventQueueManager m_EventQueueManager; // Executes events 49 public EventQueueManager m_EventQueueManager; // Executes events, handles script threads
50 public ScriptManager m_ScriptManager; // Load, unload and execute scripts 50 public ScriptManager m_ScriptManager; // Load, unload and execute scripts
51 public AppDomainManager m_AppDomainManager; 51 public AppDomainManager m_AppDomainManager; // Handles loading/unloading of scripts into AppDomains
52 public LSLLongCmdHandler m_LSLLongCmdHandler; 52 public AsyncLSLCommandManager m_ASYNCLSLCommandManager; // Asyncronous LSL commands (commands that returns with an event)
53 public MaintenanceThread m_MaintenanceThread; // Thread that does different kinds of maintenance, for example refreshing config and killing scripts that has been running too long
53 54
54 public IConfigSource ConfigSource; 55 public IConfigSource ConfigSource;
55 public IConfig ScriptConfigSource; 56 public IConfig ScriptConfigSource;
56 public abstract string ScriptConfigSourceName { get; } 57 public abstract string ScriptEngineName { get; }
57 58
58 /// <summary> 59 /// <summary>
59 /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. 60 /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes.
60 /// </summary> 61 /// </summary>
61 public int ReReadConfigFileSeconds { 62 public int RefreshConfigFileSeconds {
62 get { return (int)(ReReadConfigFilens / 10000); } 63 get { return (int)(RefreshConfigFilens / 10000); }
63 set { ReReadConfigFilens = value * 10000; } 64 set { RefreshConfigFilens = value * 10000; }
64 } 65 }
65 public long ReReadConfigFilens = 0; 66 public long RefreshConfigFilens = 0;
66 67
67 public ScriptManager GetScriptManager() 68 public ScriptManager GetScriptManager()
68 { 69 {
@@ -88,21 +89,22 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
88 { 89 {
89 World = Sceneworld; 90 World = Sceneworld;
90 m_log = logger; 91 m_log = logger;
91 ScriptConfigSource = ConfigSource.Configs[ScriptConfigSourceName]; 92 ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
92 93
93 Log.Verbose("ScriptEngine", "DotNet & LSL ScriptEngine initializing"); 94 Log.Verbose(ScriptEngineName, "DotNet & LSL ScriptEngine initializing");
94 95
95 //m_logger.Status("ScriptEngine", "InitializeEngine"); 96 //m_logger.Status(ScriptEngineName, "InitializeEngine");
96 97
97 // Create all objects we'll be using 98 // Create all objects we'll be using
98 m_EventQueueManager = new EventQueueManager(this); 99 m_EventQueueManager = new EventQueueManager(this);
99 m_EventManager = new EventManager(this, HookUpToServer); 100 m_EventManager = new EventManager(this, HookUpToServer);
100 m_ScriptManager = newScriptManager; 101 m_ScriptManager = newScriptManager;
101 //m_ScriptManager = new ScriptManager(this); 102 m_AppDomainManager = new AppDomainManager(this);
102 m_AppDomainManager = new AppDomainManager(ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1)); 103 m_ASYNCLSLCommandManager = new AsyncLSLCommandManager(this);
103 m_LSLLongCmdHandler = new LSLLongCmdHandler(this); 104 m_MaintenanceThread = new MaintenanceThread(this);
105
106 ReadConfig();
104 107
105 ReReadConfigFileSeconds = ScriptConfigSource.GetInt("ReReadConfig", 0);
106 108
107 109
108 // Should we iterate the region for scripts that needs starting? 110 // Should we iterate the region for scripts that needs starting?
@@ -118,6 +120,26 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
118 { 120 {
119 return this.m_EventManager; 121 return this.m_EventManager;
120 } 122 }
123 public void ReadConfig()
124 {
125#if DEBUG
126 Log.Debug(ScriptEngineName, "Refreshing configuration for all modules");
127#endif
128 RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 0);
129
130 // Reload from disk
131 ConfigSource.Reload();
132 // Create a new object (probably not necessary?)
133// ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
134
135 if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig();
136 if (m_EventManager != null) m_EventManager.ReadConfig();
137 if (m_ScriptManager != null) m_ScriptManager.ReadConfig();
138 if (m_AppDomainManager != null) m_AppDomainManager.ReadConfig();
139 if (m_ASYNCLSLCommandManager != null) m_ASYNCLSLCommandManager.ReadConfig();
140 if (m_MaintenanceThread != null) m_MaintenanceThread.ReadConfig();
141
142 }
121 143
122 144
123 #region IRegionModule 145 #region IRegionModule
@@ -134,7 +156,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
134 156
135 public string Name 157 public string Name
136 { 158 {
137 get { return "DotNetEngine"; } 159 get { return "Common." + ScriptEngineName; }
138 } 160 }
139 161
140 public bool IsSharedModule 162 public bool IsSharedModule
@@ -146,5 +168,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
146 168
147 #endregion 169 #endregion
148 170
171 /// <summary>
172 /// If set to true then threads and stuff should try to make a graceful exit
173 /// </summary>
174 public bool PleaseShutdown
175 {
176 get { return _PleaseShutdown; }
177 set { _PleaseShutdown = value; }
178 }
179 private bool _PleaseShutdown = false;
180
149 } 181 }
150} \ No newline at end of file 182} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
index ea87581..45cfced 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
@@ -57,12 +57,12 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
57 // This so that scripts starting or stopping will not slow down other theads or whole system. 57 // This so that scripts starting or stopping will not slow down other theads or whole system.
58 // 58 //
59 [Serializable] 59 [Serializable]
60 public abstract class ScriptManager 60 public abstract class ScriptManager : iScriptEngineFunctionModule
61 { 61 {
62 #region Declares 62 #region Declares
63 63
64 private Thread scriptLoadUnloadThread; 64 private Thread scriptLoadUnloadThread;
65 private int scriptLoadUnloadThread_IdleSleepms = 100; 65 private int scriptLoadUnloadThread_IdleSleepms;
66 private Queue<LUStruct> LUQueue = new Queue<LUStruct>(); 66 private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
67 67
68 68
@@ -95,6 +95,11 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
95 95
96 #endregion 96 #endregion
97 97
98 public void ReadConfig()
99 {
100 scriptLoadUnloadThread_IdleSleepms = m_scriptEngine.ScriptConfigSource.GetInt("ScriptLoadUnloadLoopms", 30);
101 }
102
98 #region Object init/shutdown 103 #region Object init/shutdown
99 104
100 public ScriptEngineBase.ScriptEngine m_scriptEngine; 105 public ScriptEngineBase.ScriptEngine m_scriptEngine;
@@ -102,6 +107,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
102 public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine) 107 public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine)
103 { 108 {
104 m_scriptEngine = scriptEngine; 109 m_scriptEngine = scriptEngine;
110 ReadConfig();
105 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 111 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
106 scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop); 112 scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop);
107 scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread"; 113 scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread";
@@ -238,7 +244,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
238 Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName); 244 Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName);
239#endif 245#endif
240 // Execute a function in the script 246 // Execute a function in the script
241 //m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); 247 //m_scriptEngine.Log.Verbose(ScriptEngineName, "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
242 //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID); 248 //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
243 IScript Script = GetScript(localID, itemID); 249 IScript Script = GetScript(localID, itemID);
244 if (Script == null) 250 if (Script == null)
@@ -345,5 +351,16 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
345 } 351 }
346 352
347 #endregion 353 #endregion
354
355 /// <summary>
356 /// If set to true then threads and stuff should try to make a graceful exit
357 /// </summary>
358 public bool PleaseShutdown
359 {
360 get { return _PleaseShutdown; }
361 set { _PleaseShutdown = value; }
362 }
363 private bool _PleaseShutdown = false;
364
348 } 365 }
349} \ No newline at end of file 366} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs
new file mode 100644
index 0000000..7539074
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs
@@ -0,0 +1,12 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
6{
7 public interface iScriptEngineFunctionModule
8 {
9 void ReadConfig();
10 bool PleaseShutdown { get; set; }
11 }
12} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
index de168b7..5ba37f7 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
48 return new ScriptManager(this); 48 return new ScriptManager(this);
49 } 49 }
50 50
51 public override string ScriptConfigSourceName 51 public override string ScriptEngineName
52 { 52 {
53 get { return "ScriptEngine.DotNetEngine"; } 53 get { return "ScriptEngine.DotNetEngine"; }
54 } 54 }
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
index 5e1b537..9cad388 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
@@ -124,7 +124,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
124 124
125 125
126 // Stop long command on script 126 // Stop long command on script
127 m_scriptEngine.m_LSLLongCmdHandler.RemoveScript(localID, itemID); 127 m_scriptEngine.m_ASYNCLSLCommandManager.RemoveScript(localID, itemID);
128 128
129 IScript LSLBC = GetScript(localID, itemID); 129 IScript LSLBC = GetScript(localID, itemID);
130 if (LSLBC == null) 130 if (LSLBC == null)
diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs
index aac210b..49727c2 100644
--- a/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.ScriptEngine.LSOEngine
52 return new ScriptManager(this); 52 return new ScriptManager(this);
53 } 53 }
54 54
55 public override string ScriptConfigSourceName 55 public override string ScriptEngineName
56 { 56 {
57 get { return "ScriptEngine.LSOEngine"; } 57 get { return "ScriptEngine.LSOEngine"; }
58 } 58 }
diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs
index de7b466..6664025 100644
--- a/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs
+++ b/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs
@@ -127,7 +127,7 @@ namespace OpenSim.Region.ScriptEngine.LSOEngine
127 127
128 128
129 // Stop long command on script 129 // Stop long command on script
130 m_scriptEngine.m_LSLLongCmdHandler.RemoveScript(localID, itemID); 130 m_scriptEngine.m_ASYNCLSLCommandManager.RemoveScript(localID, itemID);
131 131
132 IScript LSLBC = GetScript(localID, itemID); 132 IScript LSLBC = GetScript(localID, itemID);
133 if (LSLBC == null) 133 if (LSLBC == null)
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 9d664bf..94bacd1 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -123,6 +123,13 @@ shout_distance = 100
123; Same if you have 10 threads, then only 10 scripts can be run simultaneously. 123; Same if you have 10 threads, then only 10 scripts can be run simultaneously.
124; But because most scripts exit after their task, the threads are free to go on to the next script. 124; But because most scripts exit after their task, the threads are free to go on to the next script.
125 125
126; Refresh ScriptEngine config options (these settings) every xx seconds
127; 0 = Do not refresh
128; Set it to number of seconds between refresh, for example 30.
129; Will allow you to change ScriptEngine settings while server is running just by editing this file.
130; For example to increase or decrease number of threads.
131RefreshConfig=0
132
126; Number of threads to use for script event execution 133; Number of threads to use for script event execution
127; Threads are shared across all regions 134; Threads are shared across all regions
128NumberOfScriptThreads=2 135NumberOfScriptThreads=2
@@ -136,6 +143,7 @@ ScriptThreadPriority=BelowNormal
136; Number of threads will be <NumberOfScriptThreads>*<NumberOfRegions> 143; Number of threads will be <NumberOfScriptThreads>*<NumberOfRegions>
137; false: All regions share <NumberOfScriptThreads> for all their scripts 144; false: All regions share <NumberOfScriptThreads> for all their scripts
138; Note! If you run multiple script engines based on "OpenSim.Region.ScriptEngine.Common" then all of them will share the same threads. 145; Note! If you run multiple script engines based on "OpenSim.Region.ScriptEngine.Common" then all of them will share the same threads.
146; *** This setting will not work until you restart OpenSim
139PrivateRegionThreads=false 147PrivateRegionThreads=false
140 148
141; How long MAX should a script event be allowed to run (per event execution)? 149; How long MAX should a script event be allowed to run (per event execution)?
@@ -164,5 +172,14 @@ SleepTimeIfNoScriptExecutionMs=50
164; Each AppDomain has some memory overhead. But leaving dead scripts in memory also has memory overhead. 172; Each AppDomain has some memory overhead. But leaving dead scripts in memory also has memory overhead.
165ScriptsPerAppDomain=1 173ScriptsPerAppDomain=1
166 174
167; ReRead ScriptEngine config options how often? 175; Script loading / unloading sleep
168ReReadConfig=0 176; How long load/unload thread should sleep if there is nothing to do
177; Higher value makes it respond slower when scripts are added/removed from prims
178; But once active it will process all in queue before sleeping again
179ScriptLoadUnloadLoopms=30
180
181; Async LL command sleep
182; If no async LL commands are waiting, how long should thread sleep before checking again
183; Async LL commands are LSL-commands that causes an event to be fired back with result
184AsyncLLCommandLoopms=50
185