aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler
diff options
context:
space:
mode:
authorTedd Hansen2008-11-08 17:35:48 +0000
committerTedd Hansen2008-11-08 17:35:48 +0000
commit9511a8c76370f21e839114007dcd2b25c69b009a (patch)
treeb63323dfd96ecd1cc3cd560939bd66bb43ec9c1c /OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler
parent* Added IClientIM to IClientCore interfaces (diff)
downloadopensim-SC-9511a8c76370f21e839114007dcd2b25c69b009a.zip
opensim-SC-9511a8c76370f21e839114007dcd2b25c69b009a.tar.gz
opensim-SC-9511a8c76370f21e839114007dcd2b25c69b009a.tar.bz2
opensim-SC-9511a8c76370f21e839114007dcd2b25c69b009a.tar.xz
Work in progress on SECS stuff. Have been holding it off until after 0.6 release. Still messy as hell and doesn't really work yet. Will undergo dramatic changes. AND MOST IMPORTANTLY: Will be conformed to work in coop with todays DNE and XEngine, hopefully one day providing a common interface for all components.
Diffstat (limited to 'OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler')
-rw-r--r--OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/BaseClassFactory.cs213
-rw-r--r--OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/LoadUnloadStructure.cs22
-rw-r--r--OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/Scheduler.cs19
-rw-r--r--OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptLoader.cs216
-rw-r--r--OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager.cs176
-rw-r--r--OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager_ScriptLoadUnload.cs259
6 files changed, 901 insertions, 4 deletions
diff --git a/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/BaseClassFactory.cs b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/BaseClassFactory.cs
new file mode 100644
index 0000000..2f19cae
--- /dev/null
+++ b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/BaseClassFactory.cs
@@ -0,0 +1,213 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Reflection;
5using System.Reflection.Emit;
6using System.Text;
7using OpenSim.ScriptEngine.Shared;
8
9namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler
10{
11 public class BaseClassFactory
12 {
13
14
15 public static void MakeBaseClass(ScriptStructure script)
16 {
17 string asmName = "ScriptAssemblies";
18 string ModuleID = asmName;
19 string ClassID = "Script";
20 string moveToDir = "ScriptEngines";
21 string asmFileName = ModuleID + "_" + ClassID + ".dll";
22 if (!Directory.Exists(moveToDir))
23 Directory.CreateDirectory(moveToDir);
24
25 ILGenerator ilgen;
26 AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
27 new AssemblyName(asmName), AssemblyBuilderAccess.RunAndSave);
28
29 // The module builder
30 ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(ModuleID, asmFileName);
31
32 // The class builder
33 TypeBuilder classBuilder = modBuilder.DefineType(ClassID, TypeAttributes.Class | TypeAttributes.Public);
34
35 // The default constructor
36 ConstructorBuilder ctorBuilder = classBuilder.DefineDefaultConstructor(MethodAttributes.Public);
37
38
39 Type[] paramsTypeArray = new Type[] {typeof (System.ParamArrayAttribute)};
40 Type[] executeFunctionTypeArray = new Type[] {typeof (string), typeof (System.ParamArrayAttribute)};
41 foreach (IScriptCommandProvider cp in script.RegionInfo.CommandProviders.Values)
42 {
43 Type t = cp.GetType();
44 foreach (MethodInfo mi in t.GetMethods())
45 {
46 MethodBuilder methodBuilder = classBuilder.DefineMethod(mi.Name, mi.Attributes, mi.GetType(), Type.EmptyTypes);
47 methodBuilder.SetParameters(paramsTypeArray);
48 //ParameterBuilder paramBuilder = methodBuilder.DefineParameter(1, ParameterAttributes.None, "args");
49
50 ilgen = methodBuilder.GetILGenerator();
51 //ilgen.Emit(OpCodes.Nop);
52 //ilgen.Emit(OpCodes.Ldarg_0);
53 //ilgen.Emit(OpCodes.Ldc_I4_0);
54 //ilgen.Emit(OpCodes.Ldelem_Ref);
55 //ilgen.MarkSequencePoint(doc, 6, 1, 6, 100);
56
57 MethodInfo ExecuteFunction = typeof(ScriptAssemblies.IScript).GetMethod(
58 "ExecuteFunction",
59 executeFunctionTypeArray);
60
61 ilgen.DeclareLocal(typeof(string));
62 ilgen.Emit(OpCodes.Nop);
63 ilgen.Emit(OpCodes.Ldstr, mi.Name);
64 ilgen.Emit(OpCodes.Stloc_0);
65 ilgen.Emit(OpCodes.Ldarg_0);
66 ilgen.Emit(OpCodes.Ldloc_0);
67 ilgen.Emit(OpCodes.Ldarg_1);
68
69 // FieldInfo testInfo = classBuilder.
70 //BindingFlags.NonPublic | BindingFlags.Instance);
71
72 //ilgen.Emit(OpCodes.Ldfld, testInfo);
73
74 //ilgen.EmitCall(OpCodes.Call, ExecuteFunction, executeFunctionTypeArray);
75 ilgen.EmitCall(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine"), executeFunctionTypeArray);
76
77 // // string.Format("Hello, {0} World!", toWhom)
78 // //
79 // ilgen.Emit(OpCodes.Ldstr, "Hello, {0} World!");
80 // ilgen.Emit(OpCodes.Ldarg_1);
81 // ilgen.Emit(OpCodes.Call, typeof(string).GetMethod
82 //("Format", new Type[] { typeof(string), typeof(object) }));
83
84 // // Console.WriteLine("Hello, World!");
85 // //
86 // ilgen.Emit(OpCodes.Call, typeof(Console).GetMethod
87 // ("WriteLine", new Type[] { typeof(string) }));
88 ilgen.Emit(OpCodes.Ret);
89
90
91
92 //Label eom = ilgen.DefineLabel();
93 //ilgen.Emit(OpCodes.Br_S, eom);
94 //ilgen.MarkLabel(eom);
95 //ilgen.Emit(OpCodes.Ret);
96 //Type test = methodBuilder.SetParameters();
97
98
99 //methodBuilder.SetParameters(typeof (object[]));
100
101
102 }
103 }
104
105
106 //// Two fields: m_firstname, m_lastname
107 //FieldBuilder fBuilderFirstName = classBuilder.DefineField("m_firstname", typeof(string), FieldAttributes.Private);
108 //FieldBuilder fBuilderLastName = classBuilder.DefineField("m_lastname", typeof(string), FieldAttributes.Private);
109
110 //// Two properties for this object: FirstName, LastName
111 //PropertyBuilder pBuilderFirstName = classBuilder.DefineProperty("FirstName", System.Reflection.PropertyAttributes.HasDefault, typeof(string), null);
112 //PropertyBuilder pBuilderLastName = classBuilder.DefineProperty("LastName", System.Reflection.PropertyAttributes.HasDefault, typeof(string), null);
113
114 //// Custom attributes for get, set accessors
115 //MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName;
116
117 //// get,set accessors for FirstName
118 //MethodBuilder mGetFirstNameBuilder = classBuilder.DefineMethod("get_FirstName", getSetAttr, typeof(string), Type.EmptyTypes);
119
120 //// Code generation
121 //ilgen = mGetFirstNameBuilder.GetILGenerator();
122 //ilgen.Emit(OpCodes.Ldarg_0);
123 //ilgen.Emit(OpCodes.Ldfld, fBuilderFirstName); // returning the firstname field
124 //ilgen.Emit(OpCodes.Ret);
125
126 //MethodBuilder mSetFirstNameBuilder = classBuilder.DefineMethod("set_FirstName", getSetAttr, null, new Type[] { typeof(string) });
127
128 //// Code generation
129 //ilgen = mSetFirstNameBuilder.GetILGenerator();
130 //ilgen.Emit(OpCodes.Ldarg_0);
131 //ilgen.Emit(OpCodes.Ldarg_1);
132 //ilgen.Emit(OpCodes.Stfld, fBuilderFirstName); // setting the firstname field from the first argument (1)
133 //ilgen.Emit(OpCodes.Ret);
134
135 //// get,set accessors for LastName
136 //MethodBuilder mGetLastNameBuilder = classBuilder.DefineMethod("get_LastName", getSetAttr, typeof(string), Type.EmptyTypes);
137
138 //// Code generation
139 //ilgen = mGetLastNameBuilder.GetILGenerator();
140 //ilgen.Emit(OpCodes.Ldarg_0);
141 //ilgen.Emit(OpCodes.Ldfld, fBuilderLastName); // returning the firstname field
142 //ilgen.Emit(OpCodes.Ret);
143
144 //MethodBuilder mSetLastNameBuilder = classBuilder.DefineMethod("set_LastName", getSetAttr, null, new Type[] { typeof(string) });
145
146 //// Code generation
147 //ilgen = mSetLastNameBuilder.GetILGenerator();
148 //ilgen.Emit(OpCodes.Ldarg_0);
149 //ilgen.Emit(OpCodes.Ldarg_1);
150 //ilgen.Emit(OpCodes.Stfld, fBuilderLastName); // setting the firstname field from the first argument (1)
151 //ilgen.Emit(OpCodes.Ret);
152
153 //// Assigning get/set accessors
154 //pBuilderFirstName.SetGetMethod(mGetFirstNameBuilder);
155 //pBuilderFirstName.SetSetMethod(mSetFirstNameBuilder);
156
157 //pBuilderLastName.SetGetMethod(mGetLastNameBuilder);
158 //pBuilderLastName.SetSetMethod(mSetLastNameBuilder);
159
160 //// Now, a custom method named GetFullName that concatenates FirstName and LastName properties
161 //MethodBuilder mGetFullNameBuilder = classBuilder.DefineMethod("GetFullName", MethodAttributes.Public, typeof(string), Type.EmptyTypes);
162
163 //// Code generation
164 //ilgen = mGetFullNameBuilder.GetILGenerator();
165 //ilgen.Emit(OpCodes.Ldarg_0);
166 //ilgen.Emit(OpCodes.Call, mGetFirstNameBuilder); // getting the firstname
167 //ilgen.Emit(OpCodes.Ldstr, " "); // an space
168 //ilgen.Emit(OpCodes.Ldarg_0);
169 //ilgen.Emit(OpCodes.Call, mGetLastNameBuilder); // getting the lastname
170
171 //// We need the 'Concat' method from string type
172 //MethodInfo concatMethod = typeof(String).GetMethod("Concat", new Type[] { typeof(string), typeof(string), typeof(string) });
173
174 //ilgen.Emit(OpCodes.Call, concatMethod); // calling concat and returning the result
175 //ilgen.Emit(OpCodes.Ret);
176
177 //// Another constructor that initializes firstname and lastname
178 //ConstructorBuilder ctorBuilder2 = classBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(string), typeof(string) });
179 //ctorBuilder2.DefineParameter(1, ParameterAttributes.In, "firstname");
180 //ctorBuilder2.DefineParameter(2, ParameterAttributes.In, "lastname");
181
182 //// Code generation
183 //ilgen = ctorBuilder2.GetILGenerator();
184
185 //// First of all, we need to call the base constructor,
186 //// the Object's constructor in this sample
187 //Type objType = Type.GetType("System.Object");
188 //ConstructorInfo objCtor = objType.GetConstructor(Type.EmptyTypes);
189
190 //ilgen.Emit(OpCodes.Ldarg_0);
191 //ilgen.Emit(OpCodes.Call, objCtor); // calling the Object's constructor
192
193 //ilgen.Emit(OpCodes.Ldarg_0);
194 //ilgen.Emit(OpCodes.Ldarg_1);
195 //ilgen.Emit(OpCodes.Call, mSetFirstNameBuilder); // setting the firstname field from the first argument (1)
196 //ilgen.Emit(OpCodes.Ldarg_0);
197 //ilgen.Emit(OpCodes.Ldarg_2);
198 //ilgen.Emit(OpCodes.Call, mSetLastNameBuilder); // setting the lastname field from the second argument (2)
199 //ilgen.Emit(OpCodes.Ret);
200
201 // Finally, create the type and save the assembly
202 classBuilder.CreateType();
203
204 asmBuilder.Save(asmFileName);
205 string toFile = Path.Combine(moveToDir, asmFileName);
206 if (File.Exists(toFile))
207 File.Delete(toFile);
208 File.Move(asmFileName, toFile);
209
210 string a = "";
211 }
212 }
213} \ No newline at end of file
diff --git a/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/LoadUnloadStructure.cs b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/LoadUnloadStructure.cs
new file mode 100644
index 0000000..d3d0509
--- /dev/null
+++ b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/LoadUnloadStructure.cs
@@ -0,0 +1,22 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using OpenSim.ScriptEngine.Shared;
5
6namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler
7{
8 public struct LoadUnloadStructure
9 {
10 public ScriptStructure Script;
11 public LUType Action;
12 public bool PostOnRez;
13 public int StartParam;
14
15 public enum LUType
16 {
17 Unknown = 0,
18 Load = 1,
19 Unload = 2
20 }
21 }
22}
diff --git a/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/Scheduler.cs b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/Scheduler.cs
index 52c59eb..1143b03 100644
--- a/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/Scheduler.cs
+++ b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/Scheduler.cs
@@ -27,18 +27,29 @@
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30using OpenSim.ApplicationPlugins.ScriptEngine.Components; 30using OpenMetaverse;
31using OpenSim.ScriptEngine.Shared;
31 32
32namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler 33namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler
33{ 34{
34 public class Scheduler: SchedulerBase 35 public class Scheduler : IScriptScheduler
35 { 36 {
36 public override void Start() 37
38 private ScriptManager m_ScriptManager = new ScriptManager();
39 public void AddScript(ScriptStructure scriptStructure)
37 { 40 {
41 m_ScriptManager.AddScript(scriptStructure);
38 } 42 }
39 43
40 public override void Close() 44 public void Removecript(uint id, UUID itemID)
41 { 45 {
46 m_ScriptManager.RemoveScript(id, itemID);
42 } 47 }
48
49 public void Close()
50 {
51 m_ScriptManager.Close();
52 }
53
43 } 54 }
44} 55}
diff --git a/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptLoader.cs b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptLoader.cs
new file mode 100644
index 0000000..cb4a870
--- /dev/null
+++ b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptLoader.cs
@@ -0,0 +1,216 @@
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 */
27using System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using log4net;
33using OpenSim.ScriptEngine.Shared;
34using IScript=OpenSim.Region.ScriptEngine.Shared.ScriptBase.IScript;
35
36namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler
37{
38 public class ScriptLoader : IScriptLoader
39 {
40 //
41 // This class does AppDomain handling and loading/unloading of
42 // scripts in it. It is instanced in "ScriptEngine" and controlled
43 // from "ScriptManager"
44 //
45 // 1. Create a new AppDomain if old one is full (or doesn't exist)
46 // 2. Load scripts into AppDomain
47 // 3. Unload scripts from AppDomain (stopping them and marking
48 // them as inactive)
49 // 4. Unload AppDomain completely when all scripts in it has stopped
50 //
51
52 public string Name { get { return "SECS.DotNetEngine.Scheduler.ScriptLoader"; } }
53 private int maxScriptsPerAppDomain = 10;
54
55 // Internal list of all AppDomains
56 private List<AppDomainStructure> appDomains =
57 new List<AppDomainStructure>();
58 private Dictionary<string, AppDomainStructure> AppDomainFiles = new Dictionary<string, AppDomainStructure>();
59 public readonly string[] AssembliesInAppDomain = new string[] { "OpenSim.ScriptEngine.Shared.Script.dll", "OpenSim.Region.ScriptEngine.Shared.dll" };
60
61 internal static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62
63 // Structure to keep track of data around AppDomain
64 private class AppDomainStructure
65 {
66 public AppDomain CurrentAppDomain; // The AppDomain itself
67 public int ScriptsLoaded; // Number of scripts loaded into AppDomain
68 public int ScriptsWaitingUnload; // Number of dead scripts
69 }
70
71 // Current AppDomain
72 private AppDomainStructure currentAD;
73
74 private object getLock = new object(); // Mutex
75 private object freeLock = new object(); // Mutex
76
77 // Find a free AppDomain, creating one if necessary
78 private AppDomainStructure GetFreeAppDomain()
79 {
80 lock (getLock)
81 {
82 // Current full?
83 if (currentAD != null &&
84 currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
85 {
86 // Add it to AppDomains list and empty current
87 appDomains.Add(currentAD);
88 currentAD = null;
89 }
90 // No current
91 if (currentAD == null)
92 {
93 // Create a new current AppDomain
94 currentAD = new AppDomainStructure();
95 currentAD.CurrentAppDomain = PrepareNewAppDomain();
96 }
97
98 return currentAD;
99 }
100 }
101
102 private int AppDomainNameCount;
103 public ScriptAssemblies.IScript LoadScript(ScriptStructure script)
104 {
105 // Find next available AppDomain to put it in
106 AppDomainStructure FreeAppDomain;
107
108 // If we already have loaded file, then reuse that AppDomains
109 if (AppDomainFiles.ContainsKey(script.AssemblyFileName))
110 FreeAppDomain = AppDomainFiles[script.AssemblyFileName];
111 else
112 FreeAppDomain = GetFreeAppDomain();
113
114 // Set script object AppDomain
115 script.AppDomain = FreeAppDomain.CurrentAppDomain;
116
117 // Create instance of script
118 ScriptAssemblies.IScript mbrt = (ScriptAssemblies.IScript)
119 FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(
120 script.AssemblyFileName, "ScriptAssemblies.Script");
121 //, true, BindingFlags.CreateInstance, null);
122 FreeAppDomain.ScriptsLoaded++;
123
124 return mbrt;
125 }
126
127 // Create and prepare a new AppDomain for scripts
128 private AppDomain PrepareNewAppDomain()
129 {
130 // Create and prepare a new AppDomain
131 AppDomainNameCount++;
132
133 // TODO: Currently security match current appdomain
134
135 // Construct and initialize settings for a second AppDomain.
136 AppDomainSetup ads = new AppDomainSetup();
137 ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
138 ads.DisallowBindingRedirects = true;
139 ads.DisallowCodeDownload = true;
140 ads.LoaderOptimization = LoaderOptimization.MultiDomainHost;
141 ads.ShadowCopyFiles = "false"; // Disable shadowing
142 ads.ConfigurationFile =
143 AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
144
145 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" +
146 AppDomainNameCount, null, ads);
147
148 foreach (string file in AssembliesInAppDomain)
149 {
150 m_log.InfoFormat("[{0}] AppDomain Loading: \"{1}\"->\"{2}\".", Name, file,
151 AssemblyName.GetAssemblyName(file).ToString());
152 AD.Load(AssemblyName.GetAssemblyName(file));
153 }
154
155 // Return the new AppDomain
156 return AD;
157 }
158
159 // Unload appdomains that are full and have only dead scripts
160 private void UnloadAppDomains()
161 {
162 lock (freeLock)
163 {
164 // Go through all
165 foreach (AppDomainStructure ads in new ArrayList(appDomains))
166 {
167 // Don't process current AppDomain
168 if (ads.CurrentAppDomain != currentAD.CurrentAppDomain)
169 {
170 // Not current AppDomain
171 // Is number of unloaded bigger or equal to number of loaded?
172 if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload)
173 {
174 // Remove from internal list
175 appDomains.Remove(ads);
176
177 // Unload
178 AppDomain.Unload(ads.CurrentAppDomain);
179 }
180 }
181 }
182 }
183 }
184
185 // Increase "dead script" counter for an AppDomain
186 public void StopScript(AppDomain ad)
187 {
188 lock (freeLock)
189 {
190 // Check if it is current AppDomain
191 if (currentAD.CurrentAppDomain == ad)
192 {
193 // Yes - increase
194 currentAD.ScriptsWaitingUnload++;
195 return;
196 }
197
198 // Lopp through all AppDomains
199 foreach (AppDomainStructure ads in new ArrayList(appDomains))
200 {
201 if (ads.CurrentAppDomain == ad)
202 {
203 // Found it
204 ads.ScriptsWaitingUnload++;
205 break;
206 }
207 }
208 }
209
210 UnloadAppDomains(); // Outsite lock, has its own GetLock
211 }
212
213
214
215 }
216} \ No newline at end of file
diff --git a/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager.cs b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager.cs
new file mode 100644
index 0000000..3452b03
--- /dev/null
+++ b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager.cs
@@ -0,0 +1,176 @@
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Reflection;
5using System.Text;
6using System.Threading;
7using log4net;
8using OpenMetaverse;
9using OpenSim.Region.ScriptEngine.Shared;
10using OpenSim.ScriptEngine.Shared;
11using EventParams=OpenSim.ScriptEngine.Shared.EventParams;
12
13namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler
14{
15 public partial class ScriptManager: IScriptExecutor
16 {
17 private const int NoWorkSleepMs = 50;
18 private const int NoWorkSleepMsInc = 1; // How much time to increase wait with on every iteration
19 private const int NoWorkSleepMsIncMax = 300; // Max time to wait
20
21 internal static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
22 public string Name { get { return "SECS.DotNetEngine.ScriptManager"; } }
23 private static Thread ScriptLoadUnloadThread;
24 public Dictionary<uint, Dictionary<UUID, ScriptStructure>> Scripts = new Dictionary<uint, Dictionary<UUID, ScriptStructure>>();
25
26 private RegionInfoStructure CurrentRegion;
27 public void Initialize(RegionInfoStructure currentRegion)
28 {
29 CurrentRegion = currentRegion;
30 }
31
32 public ScriptManager()
33 {
34 ScriptLoadUnloadThread = new Thread(LoadUnloadLoop);
35 ScriptLoadUnloadThread.Name = "ScriptLoadUnloadThread";
36 ScriptLoadUnloadThread.IsBackground = true;
37 ScriptLoadUnloadThread.Start();
38 }
39 public void Close() { }
40
41 private void LoadUnloadLoop ()
42 {
43 int _NoWorkSleepMsInc = 0;
44 while (true)
45 {
46 if (DoScriptLoadUnload())
47 {
48 // We found work, reset counter
49 _NoWorkSleepMsInc = NoWorkSleepMs;
50 } else
51 {
52 // We didn't find work
53 // Sleep
54 Thread.Sleep(NoWorkSleepMs + NoWorkSleepMsInc);
55 // Increase sleep delay
56 _NoWorkSleepMsInc += NoWorkSleepMsInc;
57 // Make sure we don't exceed max
58 if (_NoWorkSleepMsInc > NoWorkSleepMsIncMax)
59 _NoWorkSleepMsInc = NoWorkSleepMsIncMax;
60 }
61 }
62 }
63
64 #region Add/Remove/Find script functions for our Script memory structure
65 private void MemAddScript(ScriptStructure script)
66 {
67 lock (scriptLock)
68 {
69 // Create object if it doesn't exist
70 if (!Scripts.ContainsKey(script.LocalID))
71 Scripts.Add(script.LocalID, new Dictionary<UUID, ScriptStructure>());
72
73 // Delete script if it exists
74 Dictionary<UUID, ScriptStructure> Obj;
75 if (Scripts.TryGetValue(script.LocalID, out Obj))
76 if (Obj.ContainsKey(script.ItemID) == true)
77 Obj.Remove(script.ItemID);
78
79 // Add to object
80 Obj.Add(script.ItemID, script);
81 }
82 }
83 private void MemRemoveScript(uint LocalID, UUID ItemID)
84 {
85 // TODO: Also clean up command queue and async commands for object
86 lock (scriptLock)
87 {
88 // Create object if it doesn't exist
89 if (!Scripts.ContainsKey(LocalID))
90 return;
91
92 // Delete script if it exists
93 Dictionary<UUID, ScriptStructure> Obj;
94 if (Scripts.TryGetValue(LocalID, out Obj))
95 if (Obj.ContainsKey(ItemID) == true)
96 Obj.Remove(ItemID);
97
98 // Empty?
99 if (Obj.Count == 0)
100 Scripts.Remove(LocalID);
101
102 }
103 }
104 public bool TryGetScript(uint localID, UUID itemID, ref ScriptStructure script)
105 {
106 lock (scriptLock)
107 {
108
109 if (Scripts.ContainsKey(localID) == false)
110 return false;
111
112 Dictionary<UUID, ScriptStructure> Obj;
113 if (Scripts.TryGetValue(localID, out Obj))
114 if (Obj.ContainsKey(itemID) == false)
115 return false;
116
117 // Get script
118 return Obj.TryGetValue(itemID, out script);
119 }
120 }
121 public ScriptStructure GetScript(uint localID, UUID itemID)
122 {
123 lock (scriptLock)
124 {
125
126 if (Scripts.ContainsKey(localID) == false)
127 throw new Exception("No script with LocalID " + localID + " was found.");
128
129 Dictionary<UUID, ScriptStructure> Obj;
130 if (Scripts.TryGetValue(localID, out Obj))
131 if (Obj.ContainsKey(itemID) == false)
132 throw new Exception("No script with ItemID " + itemID + " was found.");
133
134 // Get script
135 return Obj[itemID];
136 }
137 }
138 public bool TryGetScripts(uint localID, ref Dictionary<UUID, ScriptStructure> returnList)
139 {
140 Dictionary<UUID, ScriptStructure> getList = GetScripts(localID);
141 if (getList != null)
142 {
143 returnList = getList;
144 return true;
145 }
146 return false;
147 }
148 public Dictionary<UUID, ScriptStructure> GetScripts(uint localID)
149 {
150 lock (scriptLock)
151 {
152
153 if (Scripts.ContainsKey(localID) == false)
154 return null;
155 return Scripts[localID];
156 }
157 }
158 #endregion
159
160 public void ExecuteCommand(EventParams p)
161 {
162 ScriptStructure ss = new ScriptStructure();
163 if (TryGetScript(p.LocalID, p.ItemID, ref ss))
164 ExecuteCommand(ref ss, p);
165 }
166
167 public void ExecuteCommand(ref ScriptStructure scriptContainer, EventParams p)
168 {
169 m_log.DebugFormat("[{0}] ######################################################", Name);
170 m_log.DebugFormat("[{0}] Command execution ItemID {1}: \"{2}\".", Name, scriptContainer.ItemID, p.EventName);
171 scriptContainer.ExecuteEvent(p);
172 m_log.DebugFormat("[{0}] ######################################################", Name);
173 }
174
175 }
176}
diff --git a/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager_ScriptLoadUnload.cs b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager_ScriptLoadUnload.cs
new file mode 100644
index 0000000..7d362f9
--- /dev/null
+++ b/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager_ScriptLoadUnload.cs
@@ -0,0 +1,259 @@
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.Reflection;
5using System.Text;
6using System.Threading;
7using log4net;
8using OpenMetaverse;
9using OpenSim.Framework;
10using OpenSim.Region.Environment.Scenes;
11using OpenSim.Region.ScriptEngine.Interfaces;
12using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
13using OpenSim.ScriptEngine.Shared;
14
15namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler
16{
17 public partial class ScriptManager
18 {
19 private Queue<LoadUnloadStructure> LUQueue = new Queue<LoadUnloadStructure>();
20 private int LoadUnloadMaxQueueSize = 500;
21 private Object scriptLock = new Object();
22 //private Dictionary<InstanceData, DetectParams[]> detparms = new Dictionary<InstanceData, DetectParams[]>();
23
24 // Load/Unload structure
25
26
27 public void AddScript(ScriptStructure script)
28 {
29 lock (LUQueue)
30 {
31 if ((LUQueue.Count >= LoadUnloadMaxQueueSize))
32 {
33 m_log.ErrorFormat("[{0}] ERROR: Load queue count is at {1} of max {2}. Ignoring load request for script LocalID: {3}, ItemID: {4}.",
34 Name, LUQueue.Count, LoadUnloadMaxQueueSize, script.LocalID, script.ItemID);
35 return;
36 }
37
38 LoadUnloadStructure ls = new LoadUnloadStructure();
39 ls.Script = script;
40 ls.Action = LoadUnloadStructure.LUType.Load;
41 LUQueue.Enqueue(ls);
42 }
43
44 }
45 public void RemoveScript(uint localID, UUID itemID)
46 {
47 LoadUnloadStructure ls = new LoadUnloadStructure();
48
49 // See if we can find script
50 if (!TryGetScript(localID, itemID, ref ls.Script))
51 {
52 // Set manually
53 ls.Script.LocalID = localID;
54 ls.Script.ItemID = itemID;
55 }
56 ls.Script.StartParam = 0;
57
58 ls.Action = LoadUnloadStructure.LUType.Unload;
59 ls.PostOnRez = false;
60
61 lock (LUQueue)
62 {
63 LUQueue.Enqueue(ls);
64 }
65 }
66
67 internal bool DoScriptLoadUnload()
68 {
69 bool ret = false;
70 // if (!m_started)
71 // return;
72
73 lock (LUQueue)
74 {
75 if (LUQueue.Count > 0)
76 {
77 LoadUnloadStructure item = LUQueue.Dequeue();
78 ret = true;
79
80 if (item.Action == LoadUnloadStructure.LUType.Unload)
81 {
82 m_log.DebugFormat("[{0}] Unloading script", Name);
83 _StopScript(item.Script.LocalID, item.Script.ItemID);
84 RemoveScript(item.Script.LocalID, item.Script.ItemID);
85 }
86 else if (item.Action == LoadUnloadStructure.LUType.Load)
87 {
88 m_log.DebugFormat("[{0}] Loading script", Name);
89 _StartScript(item);
90 }
91 }
92 }
93 return ret;
94 }
95
96 //public void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez)
97 private void _StartScript(LoadUnloadStructure ScriptObject)
98 {
99 m_log.DebugFormat(
100 "[{0}]: ScriptManager StartScript: localID: {1}, itemID: {2}",
101 Name, ScriptObject.Script.LocalID, ScriptObject.Script.ItemID);
102
103 // We will initialize and start the script.
104 // It will be up to the script itself to hook up the correct events.
105
106 SceneObjectPart m_host = ScriptObject.Script.RegionInfo.Scene.GetSceneObjectPart(ScriptObject.Script.LocalID);
107
108 if (null == m_host)
109 {
110 m_log.ErrorFormat(
111 "[{0}]: Could not find scene object part corresponding " +
112 "to localID {1} to start script",
113 Name, ScriptObject.Script.LocalID);
114
115 return;
116 }
117
118 UUID assetID = UUID.Zero;
119 TaskInventoryItem taskInventoryItem = new TaskInventoryItem();
120 if (m_host.TaskInventory.TryGetValue(ScriptObject.Script.ItemID, out taskInventoryItem))
121 assetID = taskInventoryItem.AssetID;
122
123 ScenePresence presence =
124 ScriptObject.Script.RegionInfo.Scene.GetScenePresence(taskInventoryItem.OwnerID);
125
126 CultureInfo USCulture = new CultureInfo("en-US");
127 Thread.CurrentThread.CurrentCulture = USCulture;
128
129 try
130 {
131 //
132 // Compile script to an assembly
133 //
134 //TODO: DEBUG
135 BaseClassFactory.MakeBaseClass(ScriptObject.Script);
136
137 m_log.DebugFormat("[{0}] Compiling script {1}", Name, ScriptObject.Script.Name);
138
139 string fileName = "";
140 try
141 {
142 IScriptCompiler compiler =
143 ScriptObject.Script.RegionInfo.FindCompiler(ScriptObject.Script.ScriptMetaData);
144 RegionInfoStructure currentRegionInfo = ScriptObject.Script.RegionInfo;
145 fileName = compiler.Compile(ScriptObject.Script.ScriptMetaData,
146 ref ScriptObject.Script.Source);
147 ScriptObject.Script.AssemblyFileName = fileName;
148 }
149 catch (Exception e)
150 {
151 m_log.ErrorFormat("[{0}] Internal error while compiling \"{1}\": {2}", Name, ScriptObject.Script.Name, e.ToString());
152 }
153 m_log.DebugFormat("[{0}] Compiled \"{1}\" to assembly: \"{2}\".", Name, ScriptObject.Script.Name, fileName);
154
155 // Add it to our script memstruct
156 MemAddScript(ScriptObject.Script);
157
158 ScriptAssemblies.IScript CompiledScript;
159 CompiledScript = CurrentRegion.ScriptLoader.LoadScript(ScriptObject.Script);
160 ScriptObject.Script.State = "default";
161 ScriptObject.Script.ScriptObject = CompiledScript;
162 ScriptObject.Script.Disabled = false;
163 ScriptObject.Script.Running = true;
164 //id.LineMap = LSLCompiler.LineMap();
165 //id.Script = CompiledScript;
166 //id.Source = item.Script.Script;
167 //item.StartParam = startParam;
168
169
170
171 // TODO: Fire the first start-event
172 //int eventFlags =
173 // m_scriptEngine.m_ScriptManager.GetStateEventFlags(
174 // localID, itemID);
175
176 //m_host.SetScriptEvents(itemID, eventFlags);
177 ScriptObject.Script.RegionInfo.Executors_Execute(ScriptObject.Script,
178 new EventParams(ScriptObject.Script.LocalID, ScriptObject.Script.ItemID, "state_entry", new object[] { }, new Region.ScriptEngine.Shared.DetectParams[0])
179 );
180
181 if (ScriptObject.PostOnRez)
182 {
183 ScriptObject.Script.RegionInfo.Executors_Execute(ScriptObject.Script,
184 new EventParams(ScriptObject.Script.LocalID, "on_rez", new object[]
185 {new Region.ScriptEngine.Shared.LSL_Types.LSLInteger(ScriptObject.StartParam)
186 }, new Region.ScriptEngine.Shared.DetectParams[0]));
187 }
188 }
189 catch (Exception e) // LEGIT: User Scripting
190 {
191 if (presence != null && (!ScriptObject.PostOnRez))
192 presence.ControllingClient.SendAgentAlertMessage(
193 "Script saved with errors, check debug window!",
194 false);
195 try
196 {
197 // DISPLAY ERROR INWORLD
198 string text = "Error compiling script:\n" +
199 e.Message.ToString();
200 if (text.Length > 1100)
201 text = text.Substring(0, 1099);
202
203 ScriptObject.Script.RegionInfo.Scene.SimChat(Utils.StringToBytes(text),
204 ChatTypeEnum.DebugChannel, 2147483647,
205 m_host.AbsolutePosition, m_host.Name, m_host.UUID,
206 false);
207 }
208 catch (Exception e2) // LEGIT: User Scripting
209 {
210 m_log.Error("[" +
211 Name +
212 "]: Error displaying error in-world: " +
213 e2.ToString());
214 m_log.Error("[" +
215 Name + "]: " +
216 "Errormessage: Error compiling script:\r\n" +
217 e2.Message.ToString());
218 }
219 }
220 }
221
222
223
224 public void _StopScript(uint localID, UUID itemID)
225 {
226 ScriptStructure ss = new ScriptStructure();
227 if (!TryGetScript(localID, itemID, ref ss))
228 return;
229
230 // Stop long command on script
231 //AsyncCommandManager.RemoveScript(ss);
232
233 try
234 {
235 // Get AppDomain
236 // Tell script not to accept new requests
237 ss.Running = false;
238 ss.Disabled = true;
239 AppDomain ad = ss.AppDomain;
240
241 // Remove from internal structure
242 MemRemoveScript(localID, itemID);
243
244 // TODO: Tell AppDomain that we have stopped script
245
246 }
247 catch (Exception e) // LEGIT: User Scripting
248 {
249 m_log.Error("[" +
250 Name +
251 "]: Exception stopping script localID: " +
252 localID + " LLUID: " + itemID.ToString() +
253 ": " + e.ToString());
254 }
255 }
256
257
258 }
259}