aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs (renamed from OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs)474
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs (renamed from OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs)112
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs (renamed from OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs)516
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs (renamed from OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs)725
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs (renamed from OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs)588
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs131
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs347
7 files changed, 1685 insertions, 1208 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
index 66153a7..4eea69a 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
@@ -1,238 +1,238 @@
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; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Reflection; 32using System.Reflection;
33using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; 33using OpenSim.Region.ScriptEngine.Common;
34 34
35namespace OpenSim.Region.ScriptEngine.DotNetEngine 35namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
36{ 36{
37 public class AppDomainManager 37 public class AppDomainManager
38 { 38 {
39 39
40 // 40 //
41 // This class does AppDomain handling and loading/unloading of scripts in it. 41 // This class does AppDomain handling and loading/unloading of scripts in it.
42 // It is instanced in "ScriptEngine" and controlled from "ScriptManager" 42 // It is instanced in "ScriptEngine" and controlled from "ScriptManager"
43 // 43 //
44 // 1. Create a new AppDomain if old one is full (or doesn't exist) 44 // 1. Create a new AppDomain if old one is full (or doesn't exist)
45 // 2. Load scripts into AppDomain 45 // 2. Load scripts into AppDomain
46 // 3. Unload scripts from AppDomain (stopping them and marking them as inactive) 46 // 3. Unload scripts from AppDomain (stopping them and marking them as inactive)
47 // 4. Unload AppDomain completely when all scripts in it has stopped 47 // 4. Unload AppDomain completely when all scripts in it has stopped
48 // 48 //
49 49
50 50
51 private int maxScriptsPerAppDomain = 1; 51 private int maxScriptsPerAppDomain = 1;
52 52
53 /// <summary> 53 /// <summary>
54 /// Internal list of all AppDomains 54 /// Internal list of all AppDomains
55 /// </summary> 55 /// </summary>
56 private List<AppDomainStructure> appDomains = new List<AppDomainStructure>(); 56 private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
57 57
58 /// <summary> 58 /// <summary>
59 /// Structure to keep track of data around AppDomain 59 /// Structure to keep track of data around AppDomain
60 /// </summary> 60 /// </summary>
61 private class AppDomainStructure 61 private class AppDomainStructure
62 { 62 {
63 /// <summary> 63 /// <summary>
64 /// The AppDomain itself 64 /// The AppDomain itself
65 /// </summary> 65 /// </summary>
66 public AppDomain CurrentAppDomain; 66 public AppDomain CurrentAppDomain;
67 67
68 /// <summary> 68 /// <summary>
69 /// Number of scripts loaded into AppDomain 69 /// Number of scripts loaded into AppDomain
70 /// </summary> 70 /// </summary>
71 public int ScriptsLoaded; 71 public int ScriptsLoaded;
72 72
73 /// <summary> 73 /// <summary>
74 /// Number of dead scripts 74 /// Number of dead scripts
75 /// </summary> 75 /// </summary>
76 public int ScriptsWaitingUnload; 76 public int ScriptsWaitingUnload;
77 } 77 }
78 78
79 /// <summary> 79 /// <summary>
80 /// Current AppDomain 80 /// Current AppDomain
81 /// </summary> 81 /// </summary>
82 private AppDomainStructure currentAD; 82 private AppDomainStructure currentAD;
83 83
84 private object getLock = new object(); // Mutex 84 private object getLock = new object(); // Mutex
85 private object freeLock = new object(); // Mutex 85 private object freeLock = new object(); // Mutex
86 86
87 //private ScriptEngine m_scriptEngine; 87 //private ScriptEngine m_scriptEngine;
88 //public AppDomainManager(ScriptEngine scriptEngine) 88 //public AppDomainManager(ScriptEngine scriptEngine)
89 public AppDomainManager() 89 public AppDomainManager()
90 { 90 {
91 //m_scriptEngine = scriptEngine; 91 //m_scriptEngine = scriptEngine;
92 } 92 }
93 93
94 /// <summary> 94 /// <summary>
95 /// Find a free AppDomain, creating one if necessary 95 /// Find a free AppDomain, creating one if necessary
96 /// </summary> 96 /// </summary>
97 /// <returns>Free AppDomain</returns> 97 /// <returns>Free AppDomain</returns>
98 private AppDomainStructure GetFreeAppDomain() 98 private AppDomainStructure GetFreeAppDomain()
99 { 99 {
100 Console.WriteLine("Finding free AppDomain"); 100 Console.WriteLine("Finding free AppDomain");
101 lock (getLock) 101 lock (getLock)
102 { 102 {
103 // Current full? 103 // Current full?
104 if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) 104 if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
105 { 105 {
106 // Add it to AppDomains list and empty current 106 // Add it to AppDomains list and empty current
107 appDomains.Add(currentAD); 107 appDomains.Add(currentAD);
108 currentAD = null; 108 currentAD = null;
109 } 109 }
110 // No current 110 // No current
111 if (currentAD == null) 111 if (currentAD == null)
112 { 112 {
113 // Create a new current AppDomain 113 // Create a new current AppDomain
114 currentAD = new AppDomainStructure(); 114 currentAD = new AppDomainStructure();
115 currentAD.CurrentAppDomain = PrepareNewAppDomain(); 115 currentAD.CurrentAppDomain = PrepareNewAppDomain();
116 } 116 }
117 117
118 Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded); 118 Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
119 return currentAD; 119 return currentAD;
120 } // lock 120 } // lock
121 } 121 }
122 122
123 private int AppDomainNameCount; 123 private int AppDomainNameCount;
124 124
125 /// <summary> 125 /// <summary>
126 /// Create and prepare a new AppDomain for scripts 126 /// Create and prepare a new AppDomain for scripts
127 /// </summary> 127 /// </summary>
128 /// <returns>The new AppDomain</returns> 128 /// <returns>The new AppDomain</returns>
129 private AppDomain PrepareNewAppDomain() 129 private AppDomain PrepareNewAppDomain()
130 { 130 {
131 // Create and prepare a new AppDomain 131 // Create and prepare a new AppDomain
132 AppDomainNameCount++; 132 AppDomainNameCount++;
133 // TODO: Currently security match current appdomain 133 // TODO: Currently security match current appdomain
134 134
135 // Construct and initialize settings for a second AppDomain. 135 // Construct and initialize settings for a second AppDomain.
136 AppDomainSetup ads = new AppDomainSetup(); 136 AppDomainSetup ads = new AppDomainSetup();
137 ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; 137 ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
138 ads.DisallowBindingRedirects = false; 138 ads.DisallowBindingRedirects = false;
139 ads.DisallowCodeDownload = true; 139 ads.DisallowCodeDownload = true;
140 ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;) 140 ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;)
141 ads.ShadowCopyFiles = "true"; // Enabled shadowing 141 ads.ShadowCopyFiles = "true"; // Enabled shadowing
142 ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; 142 ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
143 143
144 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); 144 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
145 Console.WriteLine("Loading: " + 145 Console.WriteLine("Loading: " +
146 AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString()); 146 AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString());
147 AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll")); 147 AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll"));
148 148
149 // Return the new AppDomain 149 // Return the new AppDomain
150 return AD; 150 return AD;
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// Unload appdomains that are full and have only dead scripts 154 /// Unload appdomains that are full and have only dead scripts
155 /// </summary> 155 /// </summary>
156 private void UnloadAppDomains() 156 private void UnloadAppDomains()
157 { 157 {
158 lock (freeLock) 158 lock (freeLock)
159 { 159 {
160 // Go through all 160 // Go through all
161 foreach (AppDomainStructure ads in new ArrayList(appDomains)) 161 foreach (AppDomainStructure ads in new ArrayList(appDomains))
162 { 162 {
163 // Don't process current AppDomain 163 // Don't process current AppDomain
164 if (ads.CurrentAppDomain != currentAD.CurrentAppDomain) 164 if (ads.CurrentAppDomain != currentAD.CurrentAppDomain)
165 { 165 {
166 // Not current AppDomain 166 // Not current AppDomain
167 // Is number of unloaded bigger or equal to number of loaded? 167 // Is number of unloaded bigger or equal to number of loaded?
168 if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) 168 if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload)
169 { 169 {
170 Console.WriteLine("Found empty AppDomain, unloading"); 170 Console.WriteLine("Found empty AppDomain, unloading");
171 // Remove from internal list 171 // Remove from internal list
172 appDomains.Remove(ads); 172 appDomains.Remove(ads);
173#if DEBUG 173#if DEBUG
174 long m = GC.GetTotalMemory(true); 174 long m = GC.GetTotalMemory(true);
175#endif 175#endif
176 // Unload 176 // Unload
177 AppDomain.Unload(ads.CurrentAppDomain); 177 AppDomain.Unload(ads.CurrentAppDomain);
178#if DEBUG 178#if DEBUG
179 Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + 179 Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) +
180 " bytes of memory"); 180 " bytes of memory");
181#endif 181#endif
182 } 182 }
183 } 183 }
184 } // foreach 184 } // foreach
185 } // lock 185 } // lock
186 } 186 }
187 187
188 188
189 public LSL_BaseClass LoadScript(string FileName) 189 public IScript LoadScript(string FileName)
190 { 190 {
191 // Find next available AppDomain to put it in 191 // Find next available AppDomain to put it in
192 AppDomainStructure FreeAppDomain = GetFreeAppDomain(); 192 AppDomainStructure FreeAppDomain = GetFreeAppDomain();
193 193
194 Console.WriteLine("Loading into AppDomain: " + FileName); 194 Console.WriteLine("Loading into AppDomain: " + FileName);
195 LSL_BaseClass mbrt = 195 IScript mbrt =
196 (LSL_BaseClass) 196 (IScript)
197 FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); 197 FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
198 //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); 198 //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
199 FreeAppDomain.ScriptsLoaded++; 199 FreeAppDomain.ScriptsLoaded++;
200 200
201 return mbrt; 201 return mbrt;
202 } 202 }
203 203
204 204
205 /// <summary> 205 /// <summary>
206 /// Increase "dead script" counter for an AppDomain 206 /// Increase "dead script" counter for an AppDomain
207 /// </summary> 207 /// </summary>
208 /// <param name="ad"></param> 208 /// <param name="ad"></param>
209 //[Obsolete("Needs fixing, needs a real purpose in life!!!")] 209 //[Obsolete("Needs fixing, needs a real purpose in life!!!")]
210 public void StopScript(AppDomain ad) 210 public void StopScript(AppDomain ad)
211 { 211 {
212 lock (freeLock) 212 lock (freeLock)
213 { 213 {
214 Console.WriteLine("Stopping script in AppDomain"); 214 Console.WriteLine("Stopping script in AppDomain");
215 // Check if it is current AppDomain 215 // Check if it is current AppDomain
216 if (currentAD.CurrentAppDomain == ad) 216 if (currentAD.CurrentAppDomain == ad)
217 { 217 {
218 // Yes - increase 218 // Yes - increase
219 currentAD.ScriptsWaitingUnload++; 219 currentAD.ScriptsWaitingUnload++;
220 return; 220 return;
221 } 221 }
222 222
223 // Lopp through all AppDomains 223 // Lopp through all AppDomains
224 foreach (AppDomainStructure ads in new ArrayList(appDomains)) 224 foreach (AppDomainStructure ads in new ArrayList(appDomains))
225 { 225 {
226 if (ads.CurrentAppDomain == ad) 226 if (ads.CurrentAppDomain == ad)
227 { 227 {
228 // Found it 228 // Found it
229 ads.ScriptsWaitingUnload++; 229 ads.ScriptsWaitingUnload++;
230 break; 230 break;
231 } 231 }
232 } // foreach 232 } // foreach
233 } // lock 233 } // lock
234 234
235 UnloadAppDomains(); // Outsite lock, has its own GetLock 235 UnloadAppDomains(); // Outsite lock, has its own GetLock
236 } 236 }
237 } 237 }
238} \ No newline at end of file 238} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs
index db9a535..00ea078 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs
@@ -1,57 +1,57 @@
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/* Original code: Tedd Hansen */ 28/* Original code: Tedd Hansen */
29namespace OpenSim.Region.ScriptEngine.DotNetEngine 29namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
30{ 30{
31 public static class Common 31 public static class Common
32 { 32 {
33 public static bool debug = true; 33 public static bool debug = true;
34 public static ScriptEngine mySE; 34 public static ScriptEngine mySE;
35 35
36 // This class just contains some static log stuff used for debugging. 36 // This class just contains some static log stuff used for debugging.
37 37
38 //public delegate void SendToDebugEventDelegate(string Message); 38 //public delegate void SendToDebugEventDelegate(string Message);
39 //public delegate void SendToLogEventDelegate(string Message); 39 //public delegate void SendToLogEventDelegate(string Message);
40 //static public event SendToDebugEventDelegate SendToDebugEvent; 40 //static public event SendToDebugEventDelegate SendToDebugEvent;
41 //static public event SendToLogEventDelegate SendToLogEvent; 41 //static public event SendToLogEventDelegate SendToLogEvent;
42 42
43 public static void SendToDebug(string Message) 43 public static void SendToDebug(string Message)
44 { 44 {
45 //if (Debug == true) 45 //if (Debug == true)
46 mySE.Log.Verbose("ScriptEngine", "Debug: " + Message); 46 mySE.Log.Verbose("ScriptEngine", "Debug: " + Message);
47 //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); 47 //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
48 } 48 }
49 49
50 public static void SendToLog(string Message) 50 public static void SendToLog(string Message)
51 { 51 {
52 //if (Debug == true) 52 //if (Debug == true)
53 mySE.Log.Verbose("ScriptEngine", "LOG: " + Message); 53 mySE.Log.Verbose("ScriptEngine", "LOG: " + Message);
54 //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); 54 //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
55 } 55 }
56 } 56 }
57} \ No newline at end of file 57} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
index a36691d..a5ad911 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
@@ -1,259 +1,259 @@
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/* Original code: Tedd Hansen */ 28/* Original code: Tedd Hansen */
29using System; 29using System;
30using libsecondlife; 30using libsecondlife;
31using OpenSim.Framework; 31using OpenSim.Framework;
32 32
33namespace OpenSim.Region.ScriptEngine.DotNetEngine 33namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
34{ 34{
35 /// <summary> 35 /// <summary>
36 /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. 36 /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
37 /// </summary> 37 /// </summary>
38 [Serializable] 38 [Serializable]
39 public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents 39 public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents
40 { 40 {
41 41
42 // 42 //
43 // Class is instanced in "ScriptEngine" and Uses "EventQueueManager" that is also instanced in "ScriptEngine". 43 // Class is instanced in "ScriptEngine" and Uses "EventQueueManager" that is also instanced in "ScriptEngine".
44 // This class needs a bit of explaining: 44 // This class needs a bit of explaining:
45 // 45 //
46 // This class it the link between an event inside OpenSim and the corresponding event in a user script being executed. 46 // This class it the link between an event inside OpenSim and the corresponding event in a user script being executed.
47 // 47 //
48 // For example when an user touches an object then the "myScriptEngine.World.EventManager.OnObjectGrab" event is fired inside OpenSim. 48 // For example when an user touches an object then the "myScriptEngine.World.EventManager.OnObjectGrab" event is fired inside OpenSim.
49 // We hook up to this event and queue a touch_start in EventQueueManager with the proper LSL parameters. 49 // We hook up to this event and queue a touch_start in EventQueueManager with the proper LSL parameters.
50 // It will then be delivered to the script by EventQueueManager. 50 // It will then be delivered to the script by EventQueueManager.
51 // 51 //
52 // You can check debug C# dump of an LSL script if you need to verify what exact parameters are needed. 52 // You can check debug C# dump of an LSL script if you need to verify what exact parameters are needed.
53 // 53 //
54 54
55 55
56 private ScriptEngine myScriptEngine; 56 private ScriptEngine myScriptEngine;
57 //public IScriptHost TEMP_OBJECT_ID; 57 //public IScriptHost TEMP_OBJECT_ID;
58 public EventManager(ScriptEngine _ScriptEngine, bool performHookUp) 58 public EventManager(ScriptEngine _ScriptEngine, bool performHookUp)
59 { 59 {
60 myScriptEngine = _ScriptEngine; 60 myScriptEngine = _ScriptEngine;
61 61
62 // Hook up to events from OpenSim 62 // Hook up to events from OpenSim
63 // We may not want to do it because someone is controlling us and will deliver events to us 63 // We may not want to do it because someone is controlling us and will deliver events to us
64 if (performHookUp) 64 if (performHookUp)
65 { 65 {
66 myScriptEngine.Log.Verbose("ScriptEngine", "Hooking up to server events"); 66 myScriptEngine.Log.Verbose("ScriptEngine", "Hooking up to server events");
67 myScriptEngine.World.EventManager.OnObjectGrab += touch_start; 67 myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
68 myScriptEngine.World.EventManager.OnRezScript += OnRezScript; 68 myScriptEngine.World.EventManager.OnRezScript += OnRezScript;
69 myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; 69 myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript;
70 // TODO: HOOK ALL EVENTS UP TO SERVER! 70 // TODO: HOOK ALL EVENTS UP TO SERVER!
71 } 71 }
72 } 72 }
73 73
74 public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) 74 public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient)
75 { 75 {
76 // Add to queue for all scripts in ObjectID object 76 // Add to queue for all scripts in ObjectID object
77 myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] {(int) 1}); 77 myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] {(int) 1});
78 } 78 }
79 79
80 public void OnRezScript(uint localID, LLUUID itemID, string script) 80 public void OnRezScript(uint localID, LLUUID itemID, string script)
81 { 81 {
82 Console.WriteLine("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " + 82 Console.WriteLine("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " +
83 script.Length); 83 script.Length);
84 myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script); 84 myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script);
85 } 85 }
86 86
87 public void OnRemoveScript(uint localID, LLUUID itemID) 87 public void OnRemoveScript(uint localID, LLUUID itemID)
88 { 88 {
89 Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString()); 89 Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString());
90 myScriptEngine.m_ScriptManager.StopScript( 90 myScriptEngine.m_ScriptManager.StopScript(
91 localID, 91 localID,
92 itemID 92 itemID
93 ); 93 );
94 } 94 }
95 95
96 // TODO: Replace placeholders below 96 // TODO: Replace placeholders below
97 // NOTE! THE PARAMETERS FOR THESE FUNCTIONS ARE NOT CORRECT! 97 // NOTE! THE PARAMETERS FOR THESE FUNCTIONS ARE NOT CORRECT!
98 // These needs to be hooked up to OpenSim during init of this class 98 // These needs to be hooked up to OpenSim during init of this class
99 // then queued in EventQueueManager. 99 // then queued in EventQueueManager.
100 // When queued in EventQueueManager they need to be LSL compatible (name and params) 100 // When queued in EventQueueManager they need to be LSL compatible (name and params)
101 101
102 public void state_exit(uint localID, LLUUID itemID) 102 public void state_exit(uint localID, LLUUID itemID)
103 { 103 {
104 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_exit"); 104 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_exit");
105 } 105 }
106 106
107 public void touch(uint localID, LLUUID itemID) 107 public void touch(uint localID, LLUUID itemID)
108 { 108 {
109 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch"); 109 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch");
110 } 110 }
111 111
112 public void touch_end(uint localID, LLUUID itemID) 112 public void touch_end(uint localID, LLUUID itemID)
113 { 113 {
114 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch_end"); 114 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch_end");
115 } 115 }
116 116
117 public void collision_start(uint localID, LLUUID itemID) 117 public void collision_start(uint localID, LLUUID itemID)
118 { 118 {
119 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_start"); 119 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_start");
120 } 120 }
121 121
122 public void collision(uint localID, LLUUID itemID) 122 public void collision(uint localID, LLUUID itemID)
123 { 123 {
124 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision"); 124 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision");
125 } 125 }
126 126
127 public void collision_end(uint localID, LLUUID itemID) 127 public void collision_end(uint localID, LLUUID itemID)
128 { 128 {
129 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_end"); 129 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_end");
130 } 130 }
131 131
132 public void land_collision_start(uint localID, LLUUID itemID) 132 public void land_collision_start(uint localID, LLUUID itemID)
133 { 133 {
134 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_start"); 134 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_start");
135 } 135 }
136 136
137 public void land_collision(uint localID, LLUUID itemID) 137 public void land_collision(uint localID, LLUUID itemID)
138 { 138 {
139 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision"); 139 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision");
140 } 140 }
141 141
142 public void land_collision_end(uint localID, LLUUID itemID) 142 public void land_collision_end(uint localID, LLUUID itemID)
143 { 143 {
144 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_end"); 144 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_end");
145 } 145 }
146 146
147 // Handled by long commands 147 // Handled by long commands
148 public void timer(uint localID, LLUUID itemID) 148 public void timer(uint localID, LLUUID itemID)
149 { 149 {
150 //myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, ""); 150 //myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "");
151 } 151 }
152 152
153 public void listen(uint localID, LLUUID itemID) 153 public void listen(uint localID, LLUUID itemID)
154 { 154 {
155 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "listen"); 155 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "listen");
156 } 156 }
157 157
158 public void on_rez(uint localID, LLUUID itemID) 158 public void on_rez(uint localID, LLUUID itemID)
159 { 159 {
160 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "on_rez"); 160 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "on_rez");
161 } 161 }
162 162
163 public void sensor(uint localID, LLUUID itemID) 163 public void sensor(uint localID, LLUUID itemID)
164 { 164 {
165 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "sensor"); 165 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "sensor");
166 } 166 }
167 167
168 public void no_sensor(uint localID, LLUUID itemID) 168 public void no_sensor(uint localID, LLUUID itemID)
169 { 169 {
170 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "no_sensor"); 170 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "no_sensor");
171 } 171 }
172 172
173 public void control(uint localID, LLUUID itemID) 173 public void control(uint localID, LLUUID itemID)
174 { 174 {
175 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "control"); 175 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "control");
176 } 176 }
177 177
178 public void money(uint localID, LLUUID itemID) 178 public void money(uint localID, LLUUID itemID)
179 { 179 {
180 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "money"); 180 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "money");
181 } 181 }
182 182
183 public void email(uint localID, LLUUID itemID) 183 public void email(uint localID, LLUUID itemID)
184 { 184 {
185 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "email"); 185 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "email");
186 } 186 }
187 187
188 public void at_target(uint localID, LLUUID itemID) 188 public void at_target(uint localID, LLUUID itemID)
189 { 189 {
190 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_target"); 190 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_target");
191 } 191 }
192 192
193 public void not_at_target(uint localID, LLUUID itemID) 193 public void not_at_target(uint localID, LLUUID itemID)
194 { 194 {
195 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_target"); 195 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_target");
196 } 196 }
197 197
198 public void at_rot_target(uint localID, LLUUID itemID) 198 public void at_rot_target(uint localID, LLUUID itemID)
199 { 199 {
200 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_rot_target"); 200 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_rot_target");
201 } 201 }
202 202
203 public void not_at_rot_target(uint localID, LLUUID itemID) 203 public void not_at_rot_target(uint localID, LLUUID itemID)
204 { 204 {
205 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_rot_target"); 205 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_rot_target");
206 } 206 }
207 207
208 public void run_time_permissions(uint localID, LLUUID itemID) 208 public void run_time_permissions(uint localID, LLUUID itemID)
209 { 209 {
210 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "run_time_permissions"); 210 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "run_time_permissions");
211 } 211 }
212 212
213 public void changed(uint localID, LLUUID itemID) 213 public void changed(uint localID, LLUUID itemID)
214 { 214 {
215 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "changed"); 215 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "changed");
216 } 216 }
217 217
218 public void attach(uint localID, LLUUID itemID) 218 public void attach(uint localID, LLUUID itemID)
219 { 219 {
220 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "attach"); 220 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "attach");
221 } 221 }
222 222
223 public void dataserver(uint localID, LLUUID itemID) 223 public void dataserver(uint localID, LLUUID itemID)
224 { 224 {
225 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "dataserver"); 225 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "dataserver");
226 } 226 }
227 227
228 public void link_message(uint localID, LLUUID itemID) 228 public void link_message(uint localID, LLUUID itemID)
229 { 229 {
230 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "link_message"); 230 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "link_message");
231 } 231 }
232 232
233 public void moving_start(uint localID, LLUUID itemID) 233 public void moving_start(uint localID, LLUUID itemID)
234 { 234 {
235 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_start"); 235 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_start");
236 } 236 }
237 237
238 public void moving_end(uint localID, LLUUID itemID) 238 public void moving_end(uint localID, LLUUID itemID)
239 { 239 {
240 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_end"); 240 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_end");
241 } 241 }
242 242
243 public void object_rez(uint localID, LLUUID itemID) 243 public void object_rez(uint localID, LLUUID itemID)
244 { 244 {
245 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "object_rez"); 245 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "object_rez");
246 } 246 }
247 247
248 public void remote_data(uint localID, LLUUID itemID) 248 public void remote_data(uint localID, LLUUID itemID)
249 { 249 {
250 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "remote_data"); 250 myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "remote_data");
251 } 251 }
252 252
253 // Handled by long commands 253 // Handled by long commands
254 public void http_response(uint localID, LLUUID itemID) 254 public void http_response(uint localID, LLUUID itemID)
255 { 255 {
256 // myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "http_response"); 256 // myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "http_response");
257 } 257 }
258 } 258 }
259} \ No newline at end of file 259} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
index e7cb489..62194df 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
@@ -1,364 +1,363 @@
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/* Original code: Tedd Hansen */ 28/* Original code: Tedd Hansen */
29using System; 29using System;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Threading; 32using System.Threading;
33using libsecondlife; 33using libsecondlife;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.Environment.Scenes.Scripting; 35using OpenSim.Region.Environment.Scenes.Scripting;
36using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; 36
37 37namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
38namespace OpenSim.Region.ScriptEngine.DotNetEngine 38{
39{ 39 /// <summary>
40 /// <summary> 40 /// EventQueueManager handles event queues
41 /// EventQueueManager handles event queues 41 /// Events are queued and executed in separate thread
42 /// Events are queued and executed in separate thread 42 /// </summary>
43 /// </summary> 43 [Serializable]
44 [Serializable] 44 public class EventQueueManager
45 internal class EventQueueManager 45 {
46 { 46
47 47 //
48 // 48 // Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine".
49 // Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine". 49 //
50 // 50 // Class purpose is to queue and execute functions that are received by "EventManager":
51 // Class purpose is to queue and execute functions that are received by "EventManager": 51 // - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution.
52 // - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution. 52 // - allowing us to prioritize and control execution of script functions.
53 // - allowing us to prioritize and control execution of script functions. 53 // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety.
54 // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety. 54 //
55 // 55 // 1. Hold an execution queue for scripts
56 // 1. Hold an execution queue for scripts 56 // 2. Use threads to process queue, each thread executes one script function on each pass.
57 // 2. Use threads to process queue, each thread executes one script function on each pass. 57 // 3. Catch any script error and process it
58 // 3. Catch any script error and process it 58 //
59 // 59 //
60 // 60 // Notes:
61 // Notes: 61 // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts.
62 // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts. 62 // Not noticeable unless server is under high load.
63 // Not noticeable unless server is under high load. 63 // * This class contains the number of threads used for script executions. Since we are not microthreading scripts yet,
64 // * This class contains the number of threads used for script executions. Since we are not microthreading scripts yet, 64 // increase number of threads to allow more concurrent script executions in OpenSim.
65 // increase number of threads to allow more concurrent script executions in OpenSim. 65 //
66 // 66
67 67
68 68 /// <summary>
69 /// <summary> 69 /// List of threads processing event queue
70 /// List of threads processing event queue 70 /// </summary>
71 /// </summary> 71 private List<Thread> eventQueueThreads = new List<Thread>();
72 private List<Thread> eventQueueThreads = new List<Thread>(); 72
73 73 private object queueLock = new object(); // Mutex lock object
74 private object queueLock = new object(); // Mutex lock object 74
75 75 /// <summary>
76 /// <summary> 76 /// How many ms to sleep if queue is empty
77 /// How many ms to sleep if queue is empty 77 /// </summary>
78 /// </summary> 78 private int nothingToDoSleepms = 50;
79 private int nothingToDoSleepms = 50; 79
80 80 /// <summary>
81 /// <summary> 81 /// How many threads to process queue with
82 /// How many threads to process queue with 82 /// </summary>
83 /// </summary> 83 private int numberOfThreads = 2;
84 private int numberOfThreads = 2; 84
85 85 /// <summary>
86 /// <summary> 86 /// Queue containing events waiting to be executed
87 /// Queue containing events waiting to be executed 87 /// </summary>
88 /// </summary> 88 private Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>();
89 private Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>(); 89
90 90 /// <summary>
91 /// <summary> 91 /// Queue item structure
92 /// Queue item structure 92 /// </summary>
93 /// </summary> 93 private struct QueueItemStruct
94 private struct QueueItemStruct 94 {
95 { 95 public uint localID;
96 public uint localID; 96 public LLUUID itemID;
97 public LLUUID itemID; 97 public string functionName;
98 public string functionName; 98 public object[] param;
99 public object[] param; 99 }
100 } 100
101 101 /// <summary>
102 /// <summary> 102 /// List of localID locks for mutex processing of script events
103 /// List of localID locks for mutex processing of script events 103 /// </summary>
104 /// </summary> 104 private List<uint> objectLocks = new List<uint>();
105 private List<uint> objectLocks = new List<uint>(); 105
106 106 private object tryLockLock = new object(); // Mutex lock object
107 private object tryLockLock = new object(); // Mutex lock object 107
108 108 private ScriptEngine m_ScriptEngine;
109 private ScriptEngine m_ScriptEngine; 109
110 110 public EventQueueManager(ScriptEngine _ScriptEngine)
111 public EventQueueManager(ScriptEngine _ScriptEngine) 111 {
112 { 112 m_ScriptEngine = _ScriptEngine;
113 m_ScriptEngine = _ScriptEngine; 113
114 114 //
115 // 115 // Start event queue processing threads (worker threads)
116 // Start event queue processing threads (worker threads) 116 //
117 // 117 for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++)
118 for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++) 118 {
119 { 119 Thread EventQueueThread = new Thread(EventQueueThreadLoop);
120 Thread EventQueueThread = new Thread(EventQueueThreadLoop); 120 eventQueueThreads.Add(EventQueueThread);
121 eventQueueThreads.Add(EventQueueThread); 121 EventQueueThread.IsBackground = true;
122 EventQueueThread.IsBackground = true; 122 EventQueueThread.Priority = ThreadPriority.BelowNormal;
123 EventQueueThread.Priority = ThreadPriority.BelowNormal; 123 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
124 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; 124 EventQueueThread.Start();
125 EventQueueThread.Start(); 125 }
126 } 126 }
127 } 127
128 128 ~EventQueueManager()
129 ~EventQueueManager() 129 {
130 { 130 // Kill worker threads
131 // Kill worker threads 131 foreach (Thread EventQueueThread in new ArrayList(eventQueueThreads))
132 foreach (Thread EventQueueThread in new ArrayList(eventQueueThreads)) 132 {
133 { 133 if (EventQueueThread != null && EventQueueThread.IsAlive == true)
134 if (EventQueueThread != null && EventQueueThread.IsAlive == true) 134 {
135 { 135 try
136 try 136 {
137 { 137 EventQueueThread.Abort();
138 EventQueueThread.Abort(); 138 EventQueueThread.Join();
139 EventQueueThread.Join(); 139 }
140 } 140 catch (Exception)
141 catch (Exception) 141 {
142 { 142 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString());
143 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString()); 143 }
144 } 144 }
145 } 145 }
146 } 146 eventQueueThreads.Clear();
147 eventQueueThreads.Clear(); 147 // Todo: Clean up our queues
148 // Todo: Clean up our queues 148 eventQueue.Clear();
149 eventQueue.Clear(); 149 }
150 } 150
151 151 /// <summary>
152 /// <summary> 152 /// Queue processing thread loop
153 /// Queue processing thread loop 153 /// </summary>
154 /// </summary> 154 private void EventQueueThreadLoop()
155 private void EventQueueThreadLoop() 155 {
156 { 156 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned");
157 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned"); 157 try
158 try 158 {
159 { 159 QueueItemStruct BlankQIS = new QueueItemStruct();
160 QueueItemStruct BlankQIS = new QueueItemStruct(); 160 while (true)
161 while (true) 161 {
162 { 162 try
163 try 163 {
164 { 164 QueueItemStruct QIS = BlankQIS;
165 QueueItemStruct QIS = BlankQIS; 165 bool GotItem = false;
166 bool GotItem = false; 166
167 167 if (eventQueue.Count == 0)
168 if (eventQueue.Count == 0) 168 {
169 { 169 // Nothing to do? Sleep a bit waiting for something to do
170 // Nothing to do? Sleep a bit waiting for something to do 170 Thread.Sleep(nothingToDoSleepms);
171 Thread.Sleep(nothingToDoSleepms); 171 }
172 } 172 else
173 else 173 {
174 { 174 // Something in queue, process
175 // Something in queue, process 175 //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
176 //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); 176
177 177 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
178 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD 178 lock (queueLock)
179 lock (queueLock) 179 {
180 { 180 GotItem = false;
181 GotItem = false; 181 for (int qc = 0; qc < eventQueue.Count; qc++)
182 for (int qc = 0; qc < eventQueue.Count; qc++) 182 {
183 { 183 // Get queue item
184 // Get queue item 184 QIS = eventQueue.Dequeue();
185 QIS = eventQueue.Dequeue(); 185
186 186 // Check if object is being processed by someone else
187 // Check if object is being processed by someone else 187 if (TryLock(QIS.localID) == false)
188 if (TryLock(QIS.localID) == false) 188 {
189 { 189 // Object is already being processed, requeue it
190 // Object is already being processed, requeue it 190 eventQueue.Enqueue(QIS);
191 eventQueue.Enqueue(QIS); 191 }
192 } 192 else
193 else 193 {
194 { 194 // We have lock on an object and can process it
195 // We have lock on an object and can process it 195 GotItem = true;
196 GotItem = true; 196 break;
197 break; 197 }
198 } 198 } // go through queue
199 } // go through queue 199 } // lock
200 } // lock 200
201 201 if (GotItem == true)
202 if (GotItem == true) 202 {
203 { 203 // Execute function
204 // Execute function 204 try
205 try 205 {
206 { 206#if DEBUG
207#if DEBUG 207 m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n"
208 m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n" 208 + "QIS.localID: " + QIS.localID
209 + "QIS.localID: " + QIS.localID 209 + ", QIS.itemID: " + QIS.itemID
210 + ", QIS.itemID: " + QIS.itemID 210 + ", QIS.functionName: " + QIS.functionName);
211 + ", QIS.functionName: " + QIS.functionName); 211#endif
212#endif 212 m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID,
213 m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID, 213 QIS.functionName, QIS.param);
214 QIS.functionName, QIS.param); 214 }
215 } 215 catch (Exception e)
216 catch (Exception e) 216 {
217 { 217 // DISPLAY ERROR INWORLD
218 // DISPLAY ERROR INWORLD 218 string text = "Error executing script function \"" + QIS.functionName + "\":\r\n";
219 string text = "Error executing script function \"" + QIS.functionName + "\":\r\n"; 219 //if (e.InnerException != null)
220 //if (e.InnerException != null) 220 //{
221 //{ 221 // Send inner exception
222 // Send inner exception 222 text += e.InnerException.Message.ToString();
223 text += e.InnerException.Message.ToString(); 223 //}
224 //} 224 //else
225 //else 225 //{
226 //{ 226 text += "\r\n";
227 text += "\r\n"; 227 // Send normal
228 // Send normal 228 text += e.Message.ToString();
229 text += e.Message.ToString(); 229 //}
230 //} 230 try
231 try 231 {
232 { 232 if (text.Length > 1500)
233 if (text.Length > 1500) 233 text = text.Substring(0, 1500);
234 text = text.Substring(0, 1500); 234 IScriptHost m_host = m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
235 IScriptHost m_host = m_ScriptEngine.World.GetSceneObjectPart(QIS.localID); 235 //if (m_host != null)
236 //if (m_host != null) 236 //{
237 //{ 237 m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0,
238 m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, 238 m_host.AbsolutePosition, m_host.Name, m_host.UUID);
239 m_host.AbsolutePosition, m_host.Name, m_host.UUID); 239 }
240 } 240 catch
241 catch 241 {
242 { 242 //}
243 //} 243 //else
244 //else 244 //{
245 //{ 245 // T oconsole
246 // T oconsole 246 m_ScriptEngine.Log.Error("ScriptEngine",
247 m_ScriptEngine.Log.Error("ScriptEngine", 247 "Unable to send text in-world:\r\n" + text);
248 "Unable to send text in-world:\r\n" + text); 248 }
249 } 249 }
250 } 250 finally
251 finally 251 {
252 { 252 ReleaseLock(QIS.localID);
253 ReleaseLock(QIS.localID); 253 }
254 } 254 }
255 } 255 } // Something in queue
256 } // Something in queue 256 }
257 } 257 catch (ThreadAbortException tae)
258 catch (ThreadAbortException tae) 258 {
259 { 259 throw tae;
260 throw tae; 260 }
261 } 261 catch (Exception e)
262 catch (Exception e) 262 {
263 { 263 m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString());
264 m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString()); 264 }
265 } 265 } // while
266 } // while 266 } // try
267 } // try 267 catch (ThreadAbortException)
268 catch (ThreadAbortException) 268 {
269 { 269 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message);
270 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message); 270 }
271 } 271 }
272 } 272
273 273 /// <summary>
274 /// <summary> 274 /// Try to get a mutex lock on localID
275 /// Try to get a mutex lock on localID 275 /// </summary>
276 /// </summary> 276 /// <param name="localID"></param>
277 /// <param name="localID"></param> 277 /// <returns></returns>
278 /// <returns></returns> 278 private bool TryLock(uint localID)
279 private bool TryLock(uint localID) 279 {
280 { 280 lock (tryLockLock)
281 lock (tryLockLock) 281 {
282 { 282 if (objectLocks.Contains(localID) == true)
283 if (objectLocks.Contains(localID) == true) 283 {
284 { 284 return false;
285 return false; 285 }
286 } 286 else
287 else 287 {
288 { 288 objectLocks.Add(localID);
289 objectLocks.Add(localID); 289 return true;
290 return true; 290 }
291 } 291 }
292 } 292 }
293 } 293
294 294 /// <summary>
295 /// <summary> 295 /// Release mutex lock on localID
296 /// Release mutex lock on localID 296 /// </summary>
297 /// </summary> 297 /// <param name="localID"></param>
298 /// <param name="localID"></param> 298 private void ReleaseLock(uint localID)
299 private void ReleaseLock(uint localID) 299 {
300 { 300 lock (tryLockLock)
301 lock (tryLockLock) 301 {
302 { 302 if (objectLocks.Contains(localID) == true)
303 if (objectLocks.Contains(localID) == true) 303 {
304 { 304 objectLocks.Remove(localID);
305 objectLocks.Remove(localID); 305 }
306 } 306 }
307 } 307 }
308 } 308
309 309
310 310 /// <summary>
311 /// <summary> 311 /// Add event to event execution queue
312 /// Add event to event execution queue 312 /// </summary>
313 /// </summary> 313 /// <param name="localID"></param>
314 /// <param name="localID"></param> 314 /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
315 /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param> 315 /// <param name="param">Array of parameters to match event mask</param>
316 /// <param name="param">Array of parameters to match event mask</param> 316 public void AddToObjectQueue(uint localID, string FunctionName, params object[] param)
317 public void AddToObjectQueue(uint localID, string FunctionName, params object[] param) 317 {
318 { 318 // Determine all scripts in Object and add to their queue
319 // Determine all scripts in Object and add to their queue 319 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName);
320 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName); 320
321 321
322 322 // Do we have any scripts in this object at all? If not, return
323 // Do we have any scripts in this object at all? If not, return 323 if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false)
324 if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false) 324 {
325 { 325 //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID.");
326 //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID."); 326 return;
327 return; 327 }
328 } 328
329 329 Dictionary<LLUUID, IScript>.KeyCollection scriptKeys =
330 Dictionary<LLUUID, LSL_BaseClass>.KeyCollection scriptKeys = 330 m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID);
331 m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID); 331
332 332 foreach (LLUUID itemID in scriptKeys)
333 foreach (LLUUID itemID in scriptKeys) 333 {
334 { 334 // Add to each script in that object
335 // Add to each script in that object 335 // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter?
336 // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? 336 AddToScriptQueue(localID, itemID, FunctionName, param);
337 AddToScriptQueue(localID, itemID, FunctionName, param); 337 }
338 } 338 }
339 } 339
340 340 /// <summary>
341 /// <summary> 341 /// Add event to event execution queue
342 /// Add event to event execution queue 342 /// </summary>
343 /// </summary> 343 /// <param name="localID"></param>
344 /// <param name="localID"></param> 344 /// <param name="itemID"></param>
345 /// <param name="itemID"></param> 345 /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
346 /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param> 346 /// <param name="param">Array of parameters to match event mask</param>
347 /// <param name="param">Array of parameters to match event mask</param> 347 public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, params object[] param)
348 public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, params object[] param) 348 {
349 { 349 lock (queueLock)
350 lock (queueLock) 350 {
351 { 351 // Create a structure and add data
352 // Create a structure and add data 352 QueueItemStruct QIS = new QueueItemStruct();
353 QueueItemStruct QIS = new QueueItemStruct(); 353 QIS.localID = localID;
354 QIS.localID = localID; 354 QIS.itemID = itemID;
355 QIS.itemID = itemID; 355 QIS.functionName = FunctionName;
356 QIS.functionName = FunctionName; 356 QIS.param = param;
357 QIS.param = param; 357
358 358 // Add it to queue
359 // Add it to queue 359 eventQueue.Enqueue(QIS);
360 eventQueue.Enqueue(QIS); 360 }
361 } 361 }
362 } 362 }
363 }
364} \ No newline at end of file 363} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs
index 1e4dc99..94241eb 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs
@@ -1,295 +1,295 @@
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.DotNetEngine 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 internal class LSLLongCmdHandler 41 public class LSLLongCmdHandler
42 { 42 {
43 private Thread cmdHandlerThread; 43 private Thread cmdHandlerThread;
44 private int cmdHandlerThreadCycleSleepms = 100; 44 private int cmdHandlerThreadCycleSleepms = 100;
45 45
46 private ScriptEngine m_ScriptEngine; 46 private ScriptEngine m_ScriptEngine;
47 47
48 public LSLLongCmdHandler(ScriptEngine _ScriptEngine) 48 public LSLLongCmdHandler(ScriptEngine _ScriptEngine)
49 { 49 {
50 m_ScriptEngine = _ScriptEngine; 50 m_ScriptEngine = _ScriptEngine;
51 51
52 // Start the thread that will be doing the work 52 // Start the thread that will be doing the work
53 cmdHandlerThread = new Thread(CmdHandlerThreadLoop); 53 cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
54 cmdHandlerThread.Name = "CmdHandlerThread"; 54 cmdHandlerThread.Name = "CmdHandlerThread";
55 cmdHandlerThread.Priority = ThreadPriority.BelowNormal; 55 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
56 cmdHandlerThread.IsBackground = true; 56 cmdHandlerThread.IsBackground = true;
57 cmdHandlerThread.Start(); 57 cmdHandlerThread.Start();
58 } 58 }
59 59
60 ~LSLLongCmdHandler() 60 ~LSLLongCmdHandler()
61 { 61 {
62 // Shut down thread 62 // Shut down thread
63 try 63 try
64 { 64 {
65 if (cmdHandlerThread != null) 65 if (cmdHandlerThread != null)
66 { 66 {
67 if (cmdHandlerThread.IsAlive == true) 67 if (cmdHandlerThread.IsAlive == true)
68 { 68 {
69 cmdHandlerThread.Abort(); 69 cmdHandlerThread.Abort();
70 cmdHandlerThread.Join(); 70 cmdHandlerThread.Join();
71 } 71 }
72 } 72 }
73 } 73 }
74 catch 74 catch
75 { 75 {
76 } 76 }
77 } 77 }
78 78
79 private void CmdHandlerThreadLoop() 79 private void CmdHandlerThreadLoop()
80 { 80 {
81 while (true) 81 while (true)
82 { 82 {
83 // Check timers 83 // Check timers
84 CheckTimerEvents(); 84 CheckTimerEvents();
85 Thread.Sleep(25); 85 Thread.Sleep(25);
86 // Check HttpRequests 86 // Check HttpRequests
87 CheckHttpRequests(); 87 CheckHttpRequests();
88 Thread.Sleep(25); 88 Thread.Sleep(25);
89 // Check XMLRPCRequests 89 // Check XMLRPCRequests
90 CheckXMLRPCRequests(); 90 CheckXMLRPCRequests();
91 Thread.Sleep(25); 91 Thread.Sleep(25);
92 // Check Listeners 92 // Check Listeners
93 CheckListeners(); 93 CheckListeners();
94 Thread.Sleep(25); 94 Thread.Sleep(25);
95 95
96 // Sleep before next cycle 96 // Sleep before next cycle
97 //Thread.Sleep(cmdHandlerThreadCycleSleepms); 97 //Thread.Sleep(cmdHandlerThreadCycleSleepms);
98 } 98 }
99 } 99 }
100 100
101 /// <summary> 101 /// <summary>
102 /// Remove a specific script (and all its pending commands) 102 /// Remove a specific script (and all its pending commands)
103 /// </summary> 103 /// </summary>
104 /// <param name="m_localID"></param> 104 /// <param name="m_localID"></param>
105 /// <param name="m_itemID"></param> 105 /// <param name="m_itemID"></param>
106 public void RemoveScript(uint localID, LLUUID itemID) 106 public void RemoveScript(uint localID, LLUUID itemID)
107 { 107 {
108 // Remove a specific script 108 // Remove a specific script
109 109
110 // Remove from: Timers 110 // Remove from: Timers
111 UnSetTimerEvents(localID, itemID); 111 UnSetTimerEvents(localID, itemID);
112 // Remove from: HttpRequest 112 // Remove from: HttpRequest
113 IHttpRequests iHttpReq = 113 IHttpRequests iHttpReq =
114 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>(); 114 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
115 iHttpReq.StopHttpRequest(localID, itemID); 115 iHttpReq.StopHttpRequest(localID, itemID);
116 } 116 }
117 117
118 #region TIMER 118 #region TIMER
119 119
120 // 120 //
121 // TIMER 121 // TIMER
122 // 122 //
123 private class TimerClass 123 private class TimerClass
124 { 124 {
125 public uint localID; 125 public uint localID;
126 public LLUUID itemID; 126 public LLUUID itemID;
127 public double interval; 127 public double interval;
128 public DateTime next; 128 public DateTime next;
129 } 129 }
130 130
131 private List<TimerClass> Timers = new List<TimerClass>(); 131 private List<TimerClass> Timers = new List<TimerClass>();
132 private object TimerListLock = new object(); 132 private object TimerListLock = new object();
133 133
134 public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec) 134 public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
135 { 135 {
136 Console.WriteLine("SetTimerEvent"); 136 Console.WriteLine("SetTimerEvent");
137 137
138 // Always remove first, in case this is a re-set 138 // Always remove first, in case this is a re-set
139 UnSetTimerEvents(m_localID, m_itemID); 139 UnSetTimerEvents(m_localID, m_itemID);
140 if (sec == 0) // Disabling timer 140 if (sec == 0) // Disabling timer
141 return; 141 return;
142 142
143 // Add to timer 143 // Add to timer
144 TimerClass ts = new TimerClass(); 144 TimerClass ts = new TimerClass();
145 ts.localID = m_localID; 145 ts.localID = m_localID;
146 ts.itemID = m_itemID; 146 ts.itemID = m_itemID;
147 ts.interval = sec; 147 ts.interval = sec;
148 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 148 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
149 lock (TimerListLock) 149 lock (TimerListLock)
150 { 150 {
151 Timers.Add(ts); 151 Timers.Add(ts);
152 } 152 }
153 } 153 }
154 154
155 public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID) 155 public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
156 { 156 {
157 // Remove from timer 157 // Remove from timer
158 lock (TimerListLock) 158 lock (TimerListLock)
159 { 159 {
160 List<TimerClass> NewTimers = new List<TimerClass>(); 160 List<TimerClass> NewTimers = new List<TimerClass>();
161 foreach (TimerClass ts in Timers) 161 foreach (TimerClass ts in Timers)
162 { 162 {
163 if (ts.localID != m_localID && ts.itemID != m_itemID) 163 if (ts.localID != m_localID && ts.itemID != m_itemID)
164 { 164 {
165 NewTimers.Add(ts); 165 NewTimers.Add(ts);
166 } 166 }
167 } 167 }
168 Timers.Clear(); 168 Timers.Clear();
169 Timers = NewTimers; 169 Timers = NewTimers;
170 } 170 }
171 } 171 }
172 172
173 public void CheckTimerEvents() 173 public void CheckTimerEvents()
174 { 174 {
175 // Nothing to do here? 175 // Nothing to do here?
176 if (Timers.Count == 0) 176 if (Timers.Count == 0)
177 return; 177 return;
178 178
179 lock (TimerListLock) 179 lock (TimerListLock)
180 { 180 {
181 // Go through all timers 181 // Go through all timers
182 foreach (TimerClass ts in Timers) 182 foreach (TimerClass ts in Timers)
183 { 183 {
184 // Time has passed? 184 // Time has passed?
185 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) 185 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
186 { 186 {
187 // Add it to queue 187 // Add it to queue
188 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", 188 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer",
189 new object[] {}); 189 new object[] {});
190 // set next interval 190 // set next interval
191 191
192 192
193 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 193 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
194 } 194 }
195 } 195 }
196 } // lock 196 } // lock
197 } 197 }
198 198
199 #endregion 199 #endregion
200 200
201 #region HTTP REQUEST 201 #region HTTP REQUEST
202 202
203 public void CheckHttpRequests() 203 public void CheckHttpRequests()
204 { 204 {
205 if (m_ScriptEngine.World == null) 205 if (m_ScriptEngine.World == null)
206 return; 206 return;
207 207
208 IHttpRequests iHttpReq = 208 IHttpRequests iHttpReq =
209 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>(); 209 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
210 210
211 HttpRequestClass httpInfo = null; 211 HttpRequestClass httpInfo = null;
212 212
213 if (iHttpReq != null) 213 if (iHttpReq != null)
214 httpInfo = iHttpReq.GetNextCompletedRequest(); 214 httpInfo = iHttpReq.GetNextCompletedRequest();
215 215
216 while (httpInfo != null) 216 while (httpInfo != null)
217 { 217 {
218 //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status); 218 //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status);
219 219
220 // Deliver data to prim's remote_data handler 220 // Deliver data to prim's remote_data handler
221 // 221 //
222 // TODO: Returning null for metadata, since the lsl function 222 // TODO: Returning null for metadata, since the lsl function
223 // only returns the byte for HTTP_BODY_TRUNCATED, which is not 223 // only returns the byte for HTTP_BODY_TRUNCATED, which is not
224 // implemented here yet anyway. Should be fixed if/when maxsize 224 // implemented here yet anyway. Should be fixed if/when maxsize
225 // is supported 225 // is supported
226 226
227 object[] resobj = new object[] 227 object[] resobj = new object[]
228 { 228 {
229 httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body 229 httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
230 }; 230 };
231 231
232 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 232 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
233 httpInfo.localID, httpInfo.itemID, "http_response", resobj 233 httpInfo.localID, httpInfo.itemID, "http_response", resobj
234 ); 234 );
235 235
236 httpInfo.Stop(); 236 httpInfo.Stop();
237 httpInfo = null; 237 httpInfo = null;
238 238
239 httpInfo = iHttpReq.GetNextCompletedRequest(); 239 httpInfo = iHttpReq.GetNextCompletedRequest();
240 } 240 }
241 } 241 }
242 242
243 #endregion 243 #endregion
244 244
245 public void CheckXMLRPCRequests() 245 public void CheckXMLRPCRequests()
246 { 246 {
247 if (m_ScriptEngine.World == null) 247 if (m_ScriptEngine.World == null)
248 return; 248 return;
249 249
250 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 250 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
251 251
252 if (xmlrpc != null) 252 if (xmlrpc != null)
253 { 253 {
254 while (xmlrpc.hasRequests()) 254 while (xmlrpc.hasRequests())
255 { 255 {
256 RPCRequestInfo rInfo = xmlrpc.GetNextRequest(); 256 RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
257 //Console.WriteLine("PICKED REQUEST"); 257 //Console.WriteLine("PICKED REQUEST");
258 258
259 //Deliver data to prim's remote_data handler 259 //Deliver data to prim's remote_data handler
260 object[] resobj = new object[] 260 object[] resobj = new object[]
261 { 261 {
262 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), "", 262 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), "",
263 rInfo.GetIntValue(), 263 rInfo.GetIntValue(),
264 rInfo.GetStrVal() 264 rInfo.GetStrVal()
265 }; 265 };
266 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 266 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
267 rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", resobj 267 rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", resobj
268 ); 268 );
269 } 269 }
270 } 270 }
271 } 271 }
272 272
273 public void CheckListeners() 273 public void CheckListeners()
274 { 274 {
275 if (m_ScriptEngine.World == null) 275 if (m_ScriptEngine.World == null)
276 return; 276 return;
277 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 277 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
278 278
279 while (comms.HasMessages()) 279 while (comms.HasMessages())
280 { 280 {
281 ListenerInfo lInfo = comms.GetNextMessage(); 281 ListenerInfo lInfo = comms.GetNextMessage();
282 282
283 //Deliver data to prim's listen handler 283 //Deliver data to prim's listen handler
284 object[] resobj = new object[] 284 object[] resobj = new object[]
285 { 285 {
286 lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() 286 lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
287 }; 287 };
288 288
289 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( 289 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
290 lInfo.GetLocalID(), lInfo.GetItemID(), "listen", resobj 290 lInfo.GetLocalID(), lInfo.GetItemID(), "listen", resobj
291 ); 291 );
292 } 292 }
293 } 293 }
294 } 294 }
295} \ No newline at end of file 295} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
new file mode 100644
index 0000000..9637252
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
@@ -0,0 +1,131 @@
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*/
28/* Original code: Tedd Hansen */
29using System;
30using Nini.Config;
31using OpenSim.Framework.Console;
32using OpenSim.Region.Environment.Interfaces;
33using OpenSim.Region.Environment.Scenes;
34using OpenSim.Region.ScriptEngine.Common;
35using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
36
37namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
38{
39 /// <summary>
40 /// This is the root object for ScriptEngine. Objects access each other trough this class.
41 /// </summary>
42 ///
43 [Serializable]
44 public abstract class ScriptEngine : IRegionModule, OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.ScriptEngine
45 {
46 public Scene World;
47 public EventManager m_EventManager; // Handles and queues incoming events from OpenSim
48 public EventQueueManager m_EventQueueManager; // Executes events
49 public ScriptManager m_ScriptManager; // Load, unload and execute scripts
50 public AppDomainManager m_AppDomainManager;
51 public LSLLongCmdHandler m_LSLLongCmdHandler;
52
53 public ScriptManager GetScriptManager()
54 {
55 return _GetScriptManager();
56 }
57 public abstract ScriptManager _GetScriptManager();
58
59 private LogBase m_log;
60
61 public ScriptEngine()
62 {
63 //Common.SendToDebug("ScriptEngine Object Initialized");
64 Common.mySE = this;
65 }
66
67 public LogBase Log
68 {
69 get { return m_log; }
70 }
71
72 public void InitializeEngine(Scene Sceneworld, LogBase logger, bool HookUpToServer, ScriptManager newScriptManager)
73 {
74 World = Sceneworld;
75 m_log = logger;
76
77 Log.Verbose("ScriptEngine", "DotNet & LSL ScriptEngine initializing");
78
79 //m_logger.Status("ScriptEngine", "InitializeEngine");
80
81 // Create all objects we'll be using
82 m_EventQueueManager = new EventQueueManager(this);
83 m_EventManager = new EventManager(this, HookUpToServer);
84 m_ScriptManager = newScriptManager;
85 //m_ScriptManager = new ScriptManager(this);
86 m_AppDomainManager = new AppDomainManager();
87 m_LSLLongCmdHandler = new LSLLongCmdHandler(this);
88
89 // Should we iterate the region for scripts that needs starting?
90 // Or can we assume we are loaded before anything else so we can use proper events?
91 }
92
93 public void Shutdown()
94 {
95 // We are shutting down
96 }
97
98 ScriptServerInterfaces.RemoteEvents ScriptServerInterfaces.ScriptEngine.EventManager()
99 {
100 return this.m_EventManager;
101 }
102
103
104 #region IRegionModule
105
106 public abstract void Initialise(Scene scene, IConfigSource config);
107
108 public void PostInitialise()
109 {
110 }
111
112 public void Close()
113 {
114 }
115
116 public string Name
117 {
118 get { return "DotNetEngine"; }
119 }
120
121 public bool IsSharedModule
122 {
123 get { return false; }
124 }
125
126
127
128 #endregion
129
130 }
131} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
new file mode 100644
index 0000000..55c9545
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
@@ -0,0 +1,347 @@
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*/
28/* Original code: Tedd Hansen */
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using System.Runtime.Serialization.Formatters.Binary;
34using System.Threading;
35using libsecondlife;
36using OpenSim.Framework;
37using OpenSim.Region.Environment.Scenes;
38using OpenSim.Region.ScriptEngine.Common;
39
40namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
41{
42 /// <summary>
43 /// Loads scripts
44 /// Compiles them if necessary
45 /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
46 /// </summary>
47 ///
48
49 // This class is as close as you get to the script without being inside script class. It handles all the dirty work for other classes.
50 // * Keeps track of running scripts
51 // * Compiles script if necessary (through "Compiler")
52 // * Loads script (through "AppDomainManager" called from for example "EventQueueManager")
53 // * Executes functions inside script (called from for example "EventQueueManager" class)
54 // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager")
55 // * Dedicated load/unload thread, and queues loading/unloading.
56 // This so that scripts starting or stopping will not slow down other theads or whole system.
57 //
58 [Serializable]
59 public abstract class ScriptManager
60 {
61 #region Declares
62
63 private Thread scriptLoadUnloadThread;
64 private int scriptLoadUnloadThread_IdleSleepms = 100;
65 private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
66
67
68 // Load/Unload structure
69 private struct LUStruct
70 {
71 public uint localID;
72 public LLUUID itemID;
73 public string script;
74 public LUType Action;
75 }
76
77 private enum LUType
78 {
79 Unknown = 0,
80 Load = 1,
81 Unload = 2
82 }
83
84 // Object<string, Script<string, script>>
85 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
86 // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
87 public Dictionary<uint, Dictionary<LLUUID, IScript>> Scripts =
88 new Dictionary<uint, Dictionary<LLUUID, IScript>>();
89
90 public Scene World
91 {
92 get { return m_scriptEngine.World; }
93 }
94
95 #endregion
96
97 #region Object init/shutdown
98
99 public ScriptEngineBase.ScriptEngine m_scriptEngine;
100
101 public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine)
102 {
103 m_scriptEngine = scriptEngine;
104 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
105 scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop);
106 scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread";
107 scriptLoadUnloadThread.IsBackground = true;
108 scriptLoadUnloadThread.Priority = ThreadPriority.BelowNormal;
109 scriptLoadUnloadThread.Start();
110 }
111
112 ~ScriptManager()
113 {
114 // Abort load/unload thread
115 try
116 {
117 if (scriptLoadUnloadThread != null)
118 {
119 if (scriptLoadUnloadThread.IsAlive == true)
120 {
121 scriptLoadUnloadThread.Abort();
122 scriptLoadUnloadThread.Join();
123 }
124 }
125 }
126 catch
127 {
128 }
129 }
130
131 #endregion
132
133 #region Load / Unload scripts (Thread loop)
134
135 private void ScriptLoadUnloadThreadLoop()
136 {
137 try
138 {
139 while (true)
140 {
141 if (LUQueue.Count == 0)
142 Thread.Sleep(scriptLoadUnloadThread_IdleSleepms);
143 if (LUQueue.Count > 0)
144 {
145 LUStruct item = LUQueue.Dequeue();
146 lock (startStopLock) // Lock so we have only 1 thread working on loading/unloading of scripts
147 {
148 if (item.Action == LUType.Unload)
149 {
150 _StopScript(item.localID, item.itemID);
151 }
152 if (item.Action == LUType.Load)
153 {
154 _StartScript(item.localID, item.itemID, item.script);
155 }
156 }
157 }
158 }
159 }
160 catch (ThreadAbortException tae)
161 {
162 string a = tae.ToString();
163 a = "";
164 // Expected
165 }
166 }
167
168 #endregion
169
170 #region Helper functions
171
172 private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
173 {
174 //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name);
175 return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null;
176 }
177
178 #endregion
179
180
181
182 #region Start/Stop/Reset script
183
184 private readonly Object startStopLock = new Object();
185
186 /// <summary>
187 /// Fetches, loads and hooks up a script to an objects events
188 /// </summary>
189 /// <param name="itemID"></param>
190 /// <param name="localID"></param>
191 public void StartScript(uint localID, LLUUID itemID, string Script)
192 {
193 LUStruct ls = new LUStruct();
194 ls.localID = localID;
195 ls.itemID = itemID;
196 ls.script = Script;
197 ls.Action = LUType.Load;
198 LUQueue.Enqueue(ls);
199 }
200
201 /// <summary>
202 /// Disables and unloads a script
203 /// </summary>
204 /// <param name="localID"></param>
205 /// <param name="itemID"></param>
206 public void StopScript(uint localID, LLUUID itemID)
207 {
208 LUStruct ls = new LUStruct();
209 ls.localID = localID;
210 ls.itemID = itemID;
211 ls.Action = LUType.Unload;
212 LUQueue.Enqueue(ls);
213 }
214
215 // Create a new instance of the compiler (reuse)
216 //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler();
217
218 public abstract void _StartScript(uint localID, LLUUID itemID, string Script);
219
220 public abstract void _StopScript(uint localID, LLUUID itemID);
221
222
223 #endregion
224
225 #region Perform event execution in script
226
227 /// <summary>
228 /// Execute a LL-event-function in Script
229 /// </summary>
230 /// <param name="localID">Object the script is located in</param>
231 /// <param name="itemID">Script ID</param>
232 /// <param name="FunctionName">Name of function</param>
233 /// <param name="args">Arguments to pass to function</param>
234 internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, object[] args)
235 {
236#if DEBUG
237 Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName);
238#endif
239 // Execute a function in the script
240 //m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
241 //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
242 IScript Script = GetScript(localID, itemID);
243 if (Script == null)
244 return;
245#if DEBUG
246 Console.WriteLine("ScriptEngine: Executing event: " + FunctionName);
247#endif
248 // Must be done in correct AppDomain, so leaving it up to the script itself
249 Script.Exec.ExecuteEvent(FunctionName, args);
250 }
251
252 #endregion
253
254 #region Internal functions to keep track of script
255
256 public Dictionary<LLUUID, IScript>.KeyCollection GetScriptKeys(uint localID)
257 {
258 if (Scripts.ContainsKey(localID) == false)
259 return null;
260
261 Dictionary<LLUUID, IScript> Obj;
262 Scripts.TryGetValue(localID, out Obj);
263
264 return Obj.Keys;
265 }
266
267 public IScript GetScript(uint localID, LLUUID itemID)
268 {
269 if (Scripts.ContainsKey(localID) == false)
270 return null;
271
272 Dictionary<LLUUID, IScript> Obj;
273 Scripts.TryGetValue(localID, out Obj);
274 if (Obj.ContainsKey(itemID) == false)
275 return null;
276
277 // Get script
278 IScript Script;
279 Obj.TryGetValue(itemID, out Script);
280
281 return Script;
282 }
283
284 public void SetScript(uint localID, LLUUID itemID, IScript Script)
285 {
286 // Create object if it doesn't exist
287 if (Scripts.ContainsKey(localID) == false)
288 {
289 Scripts.Add(localID, new Dictionary<LLUUID, IScript>());
290 }
291
292 // Delete script if it exists
293 Dictionary<LLUUID, IScript> Obj;
294 Scripts.TryGetValue(localID, out Obj);
295 if (Obj.ContainsKey(itemID) == true)
296 Obj.Remove(itemID);
297
298 // Add to object
299 Obj.Add(itemID, Script);
300 }
301
302 public void RemoveScript(uint localID, LLUUID itemID)
303 {
304 // Don't have that object?
305 if (Scripts.ContainsKey(localID) == false)
306 return;
307
308 // Delete script if it exists
309 Dictionary<LLUUID, IScript> Obj;
310 Scripts.TryGetValue(localID, out Obj);
311 if (Obj.ContainsKey(itemID) == true)
312 Obj.Remove(itemID);
313 }
314
315 #endregion
316
317
318 public void ResetScript(uint localID, LLUUID itemID)
319 {
320 string script = GetScript(localID, itemID).Source;
321 StopScript(localID, itemID);
322 StartScript(localID, itemID, script);
323 }
324
325
326 #region Script serialization/deserialization
327
328 public void GetSerializedScript(uint localID, LLUUID itemID)
329 {
330 // Serialize the script and return it
331 // Should not be a problem
332 FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID);
333 BinaryFormatter b = new BinaryFormatter();
334 b.Serialize(fs, GetScript(localID, itemID));
335 fs.Close();
336 }
337
338 public void PutSerializedScript(uint localID, LLUUID itemID)
339 {
340 // Deserialize the script and inject it into an AppDomain
341
342 // How to inject into an AppDomain?
343 }
344
345 #endregion
346 }
347} \ No newline at end of file