diff options
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.cs | 131 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs | 347 |
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 | ||
29 | using System; | 29 | using System; |
30 | using System.Collections; | 30 | using System.Collections; |
31 | using System.Collections.Generic; | 31 | using System.Collections.Generic; |
32 | using System.Reflection; | 32 | using System.Reflection; |
33 | using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; | 33 | using OpenSim.Region.ScriptEngine.Common; |
34 | 34 | ||
35 | namespace OpenSim.Region.ScriptEngine.DotNetEngine | 35 | namespace 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 */ |
29 | namespace OpenSim.Region.ScriptEngine.DotNetEngine | 29 | namespace 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 */ |
29 | using System; | 29 | using System; |
30 | using libsecondlife; | 30 | using libsecondlife; |
31 | using OpenSim.Framework; | 31 | using OpenSim.Framework; |
32 | 32 | ||
33 | namespace OpenSim.Region.ScriptEngine.DotNetEngine | 33 | namespace 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 */ |
29 | using System; | 29 | using System; |
30 | using System.Collections; | 30 | using System.Collections; |
31 | using System.Collections.Generic; | 31 | using System.Collections.Generic; |
32 | using System.Threading; | 32 | using System.Threading; |
33 | using libsecondlife; | 33 | using libsecondlife; |
34 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
35 | using OpenSim.Region.Environment.Scenes.Scripting; | 35 | using OpenSim.Region.Environment.Scenes.Scripting; |
36 | using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; | 36 | |
37 | 37 | namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |
38 | namespace 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 | ||
29 | using System; | 29 | using System; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Threading; | 31 | using System.Threading; |
32 | using libsecondlife; | 32 | using libsecondlife; |
33 | using OpenSim.Region.Environment.Interfaces; | 33 | using OpenSim.Region.Environment.Interfaces; |
34 | using OpenSim.Region.Environment.Modules; | 34 | using OpenSim.Region.Environment.Modules; |
35 | 35 | ||
36 | namespace OpenSim.Region.ScriptEngine.DotNetEngine | 36 | namespace 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 */ | ||
29 | using System; | ||
30 | using Nini.Config; | ||
31 | using OpenSim.Framework.Console; | ||
32 | using OpenSim.Region.Environment.Interfaces; | ||
33 | using OpenSim.Region.Environment.Scenes; | ||
34 | using OpenSim.Region.ScriptEngine.Common; | ||
35 | using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; | ||
36 | |||
37 | namespace 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 */ | ||
29 | using System; | ||
30 | using System.Collections.Generic; | ||
31 | using System.IO; | ||
32 | using System.Reflection; | ||
33 | using System.Runtime.Serialization.Formatters.Binary; | ||
34 | using System.Threading; | ||
35 | using libsecondlife; | ||
36 | using OpenSim.Framework; | ||
37 | using OpenSim.Region.Environment.Scenes; | ||
38 | using OpenSim.Region.ScriptEngine.Common; | ||
39 | |||
40 | namespace 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 | ||