Moved in-AppDomain event execution from Script to OpenSim.Region.ScriptEngine.Executor. Script no longer responsible for handling event calls to itself (and we can create reference cache in Executor).
							parent
							
								
									318376707d
								
							
						
					
					
						commit
						37446b0392
					
				|  | @ -1,10 +1,56 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
| using System.Reflection; | ||||
| 
 | ||||
| namespace OpenSim.Region.ScriptEngine.Common | ||||
| { | ||||
|     class Executor | ||||
|     public class Executor: MarshalByRefObject | ||||
|     { | ||||
|         /* TODO: | ||||
|          *  | ||||
|          * Needs to be common for all AppDomains - share memory too? | ||||
|          * Needs to have an instance in each AppDomain, and some way of referring it. | ||||
|          * Need to know what AppDomain a script is in so we know where to find our instance. | ||||
|          *  | ||||
|          */ | ||||
| 
 | ||||
|         private IScript m_Script; | ||||
| 
 | ||||
|         public Executor(IScript Script) | ||||
|         { | ||||
|             m_Script = Script; | ||||
|         } | ||||
|         public void ExecuteEvent(string FunctionName, object[] args) | ||||
|         { | ||||
|             // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. | ||||
|             // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! | ||||
| 
 | ||||
|             //foreach (MemberInfo mi in this.GetType().GetMembers()) | ||||
|             //{ | ||||
|             //if (mi.ToString().ToLower().Contains("default")) | ||||
|             //{ | ||||
|             //    Console.WriteLine("Member found: " + mi.ToString()); | ||||
|             //} | ||||
|             //} | ||||
| 
 | ||||
|             Type type = m_Script.GetType(); | ||||
| 
 | ||||
|             Console.WriteLine("ScriptEngine Executor.ExecuteEvent: \"" + m_Script.State() + "_event_" + FunctionName + "\""); | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 type.InvokeMember(m_Script.State() + "_event_" + FunctionName, BindingFlags.InvokeMethod, null, m_Script, args); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 // TODO: Send to correct place | ||||
|                 Console.WriteLine("ScriptEngine Exception attempting to executing script function: " + e.ToString()); | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -34,6 +34,7 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
| { | ||||
|     public interface LSL_BuiltIn_Commands_Interface | ||||
|     { | ||||
| 
 | ||||
|         string State(); | ||||
| 
 | ||||
|         double llSin(double f); | ||||
|  |  | |||
|  | @ -12,9 +12,12 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|     { | ||||
|         private int MaxScriptsPerAppDomain = 1; | ||||
|         /// <summary> | ||||
|         /// List of all AppDomains | ||||
|         /// Internal list of all AppDomains | ||||
|         /// </summary> | ||||
|         private List<AppDomainStructure> AppDomains = new List<AppDomainStructure>(); | ||||
|         /// <summary> | ||||
|         /// Structure to keep track of data around AppDomain | ||||
|         /// </summary> | ||||
|         private struct AppDomainStructure | ||||
|         { | ||||
|             /// <summary> | ||||
|  | @ -37,10 +40,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|         private object GetLock = new object(); // Mutex | ||||
|         private object FreeLock = new object(); // Mutex | ||||
| 
 | ||||
|                 private ScriptEngine m_scriptEngine; | ||||
|         public AppDomainManager(ScriptEngine scriptEngine) | ||||
|         //private ScriptEngine m_scriptEngine; | ||||
|         //public AppDomainManager(ScriptEngine scriptEngine) | ||||
|         public AppDomainManager() | ||||
|         { | ||||
|             m_scriptEngine = scriptEngine; | ||||
|             //m_scriptEngine = scriptEngine; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -54,6 +58,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|                 // Current full? | ||||
|                 if (CurrentAD.ScriptsLoaded >= MaxScriptsPerAppDomain) | ||||
|                 { | ||||
|                     // Add it to AppDomains list and empty current | ||||
|                     AppDomains.Add(CurrentAD); | ||||
|                     CurrentAD = new AppDomainStructure();    | ||||
|                 } | ||||
|  | @ -68,7 +73,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
| 
 | ||||
|                 } | ||||
| 
 | ||||
|                 // Increase number of scripts loaded | ||||
|                 // Increase number of scripts loaded into this | ||||
|                 // TODO: | ||||
|                 // - We assume that every time someone wants an AppDomain they will load into it | ||||
|                 //   if this assumption is wrong we end up with a miscount and will never unload it. | ||||
|                 //    | ||||
|                 CurrentAD.ScriptsLoaded++; | ||||
|                 // Return AppDomain | ||||
|                 return CurrentAD.CurrentAppDomain; | ||||
|  | @ -84,46 +93,19 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|         { | ||||
|             // Create and prepare a new AppDomain | ||||
|             AppDomainNameCount++; | ||||
|             // TODO: Currently security and configuration match current appdomain | ||||
|             // TODO: Currently security match current appdomain | ||||
| 
 | ||||
|             // Construct and initialize settings for a second AppDomain. | ||||
|             AppDomainSetup ads = new AppDomainSetup(); | ||||
|             ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; | ||||
|                 //Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ScriptEngines"); | ||||
|             //ads.ApplicationName = "DotNetScriptEngine"; | ||||
|             //ads.DynamicBase = ads.ApplicationBase; | ||||
|              | ||||
|             //Console.WriteLine("AppDomain BaseDirectory: " + ads.ApplicationBase); | ||||
|             ads.DisallowBindingRedirects = false; | ||||
|             ads.DisallowCodeDownload = true; | ||||
|             ads.ShadowCopyFiles = "true"; | ||||
|              | ||||
|             ads.ConfigurationFile = | ||||
|                 AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; | ||||
|             ads.ShadowCopyFiles = "true"; // Enabled shadowing | ||||
|             ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; | ||||
| 
 | ||||
|             AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); | ||||
|             //foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) | ||||
|             //{ | ||||
|             //    //Console.WriteLine("Loading: " + a.GetName(true)); | ||||
|             //    try | ||||
|             //    { | ||||
|             //        //AD.Load(a.GetName(true)); | ||||
|                      | ||||
|             //    } | ||||
|             //    catch (Exception e) | ||||
|             //    { | ||||
|             //        //Console.WriteLine("FAILED load"); | ||||
|             //    } | ||||
|                  | ||||
|             //} | ||||
| 
 | ||||
|             //Console.WriteLine("Assembly file: " + this.GetType().Assembly.CodeBase); | ||||
|             //Console.WriteLine("Assembly name: " + this.GetType().ToString()); | ||||
|             //AD.CreateInstanceFrom(this.GetType().Assembly.CodeBase, "OpenSim.Region.ScriptEngine.DotNetEngine.ScriptEngine"); | ||||
| 
 | ||||
|             //AD.Load(this.GetType().Assembly.CodeBase); | ||||
| 
 | ||||
|             Console.WriteLine("Done preparing new AppDomain."); | ||||
|             // Return the new AppDomain | ||||
|             return AD; | ||||
| 
 | ||||
|         } | ||||
|  | @ -135,14 +117,19 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|         { | ||||
|             lock (FreeLock) | ||||
|             { | ||||
|                 // Go through all | ||||
|                 foreach (AppDomainStructure ads in new System.Collections.ArrayList(AppDomains)) | ||||
|                 { | ||||
|                     // Don't process current AppDomain | ||||
|                     if (ads.CurrentAppDomain != CurrentAD.CurrentAppDomain) | ||||
|                     { | ||||
|                         // Not current AppDomain | ||||
|                         if (ads.ScriptsLoaded == ads.ScriptsWaitingUnload) | ||||
|                         // Is number of unloaded bigger or equal to number of loaded? | ||||
|                         if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) | ||||
|                         { | ||||
|                             // Remove from internal list | ||||
|                             AppDomains.Remove(ads); | ||||
|                             // Unload | ||||
|                             AppDomain.Unload(ads.CurrentAppDomain); | ||||
|                         } | ||||
|                     } | ||||
|  | @ -159,16 +146,20 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|         { | ||||
|             lock (FreeLock) | ||||
|             { | ||||
|                 // Check if it is current AppDomain | ||||
|                 if (CurrentAD.CurrentAppDomain == ad) | ||||
|                 { | ||||
|                     // Yes - increase | ||||
|                     CurrentAD.ScriptsWaitingUnload++; | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 // Lopp through all AppDomains | ||||
|                 foreach (AppDomainStructure ads in new System.Collections.ArrayList(AppDomains)) | ||||
|                 { | ||||
|                     if (ads.CurrentAppDomain == ad) | ||||
|                     { | ||||
|                         // Found it - messy code to increase structure | ||||
|                         AppDomainStructure ads2 = ads; | ||||
|                         ads2.ScriptsWaitingUnload++; | ||||
|                         AppDomains.Remove(ads); | ||||
|  | @ -178,5 +169,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|                 } // foreach | ||||
|             } // lock | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -9,8 +9,17 @@ using System.Reflection; | |||
| 
 | ||||
| namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL | ||||
| { | ||||
|     public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface | ||||
|     public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, IScript | ||||
|     { | ||||
|         private Executor m_Exec; | ||||
|         public Executor Exec { | ||||
|             get | ||||
|             { | ||||
|                 if (m_Exec == null) | ||||
|                     m_Exec = new Executor(this); | ||||
|                 return m_Exec; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public LSL_BuiltIn_Commands_Interface m_LSL_Functions; | ||||
| 
 | ||||
|  | @ -48,33 +57,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL | |||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         public void ExecuteEvent(string FunctionName, object[] args) | ||||
|         { | ||||
|             //foreach (MemberInfo mi in this.GetType().GetMembers()) | ||||
|             //{ | ||||
|                 //if (mi.ToString().ToLower().Contains("default")) | ||||
|                 //{ | ||||
|                 //    Console.WriteLine("Member found: " + mi.ToString()); | ||||
|                 //} | ||||
|             //} | ||||
| 
 | ||||
|                 Type type = this.GetType(); | ||||
| 
 | ||||
|                 Console.WriteLine("ScriptEngine Invoke: \"" + this.State() + "_event_" + FunctionName + "\""); | ||||
| 
 | ||||
|                 try | ||||
|                 { | ||||
|                     type.InvokeMember(this.State() + "_event_" + FunctionName, BindingFlags.InvokeMethod, null, this, args); | ||||
|                 } | ||||
|                 catch (Exception e) | ||||
|                 { | ||||
|                     // TODO: Send to correct place | ||||
|                     Console.WriteLine("ScriptEngine Exception attempting to executing script function: " + e.ToString()); | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         // | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler | |||
|     /// </summary> | ||||
|     public class LSL_BuiltIn_Commands: MarshalByRefObject, LSL_BuiltIn_Commands_Interface | ||||
|     { | ||||
| 
 | ||||
|         private System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); | ||||
|         private ScriptManager m_manager; | ||||
|         private IScriptHost m_host; | ||||
|  | @ -74,7 +75,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler | |||
|         public void llWhisper(int channelID, string text) | ||||
|         { | ||||
|             //Common.SendToDebug("INTERNAL FUNCTION llWhisper(" + channelID + ", \"" + text + "\");"); | ||||
|             Console.WriteLine("llWhisper Channel " + channelID + ", Text: \"" + text + "\""); | ||||
|             //Console.WriteLine("llWhisper Channel " + channelID + ", Text: \"" + text + "\""); | ||||
|             //type for whisper is 0 | ||||
|             World.SimChat(Helpers.StringToField(text), | ||||
|                           0, m_host.AbsolutePosition, m_host.Name, m_host.UUID); | ||||
|  | @ -86,7 +87,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler | |||
|         { | ||||
|             //TODO: DO SOMETHING USEFUL HERE | ||||
|             //Common.SendToDebug("INTERNAL FUNCTION llSay(" + (int)channelID + ", \"" + (string)text + "\");"); | ||||
|             Console.WriteLine("llSay Channel " + channelID + ", Text: \"" + text + "\""); | ||||
|             //Console.WriteLine("llSay Channel " + channelID + ", Text: \"" + text + "\""); | ||||
|             //type for say is 1 | ||||
| 
 | ||||
|             World.SimChat(Helpers.StringToField(text), | ||||
|  | @ -95,7 +96,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler | |||
| 
 | ||||
|         public void llShout(int channelID, string text) | ||||
|         { | ||||
|             Console.WriteLine("llShout Channel " + channelID + ", Text: \"" + text + "\""); | ||||
|             //Console.WriteLine("llShout Channel " + channelID + ", Text: \"" + text + "\""); | ||||
|             //type for shout is 2 | ||||
|             World.SimChat(Helpers.StringToField(text), | ||||
|                           2, m_host.AbsolutePosition, m_host.Name, m_host.UUID); | ||||
|  |  | |||
|  | @ -101,7 +101,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|                         QueueItemStruct QIS = EventQueue.Dequeue(); | ||||
|                         //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for ObjectID: " + QIS.ObjectID + ", ScriptID: " + QIS.ScriptID + ", FunctionName: " + QIS.FunctionName); | ||||
|                         // TODO: Execute function | ||||
|                         myScriptEngine.myScriptManager.ExecuteFunction(QIS.ObjectID, QIS.ScriptID, QIS.FunctionName, QIS.param); | ||||
|                         myScriptEngine.myScriptManager.ExecuteEvent(QIS.ObjectID, QIS.ScriptID, QIS.FunctionName, QIS.param); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|             myEventQueueManager = new EventQueueManager(this); | ||||
|             myEventManager = new EventManager(this); | ||||
|             myScriptManager = new ScriptManager(this); | ||||
|             myAppDomainManager = new AppDomainManager(this); | ||||
|             myAppDomainManager = new AppDomainManager(); | ||||
| 
 | ||||
|             // Should we iterate the region for scripts that needs starting? | ||||
|             // Or can we assume we are loaded before anything else so we can use proper events? | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|     /// <summary> | ||||
|     /// Loads scripts | ||||
|     /// Compiles them if necessary | ||||
|     /// Execute functions for EventQueueManager | ||||
|     /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution) | ||||
|     /// </summary> | ||||
|     [Serializable] | ||||
|     public class ScriptManager | ||||
|  | @ -182,18 +182,15 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|                 //OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName, ObjectID); | ||||
|                 OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName, ObjectID); | ||||
| 
 | ||||
|                 //string FullScriptID = ScriptID + "." + ObjectID;                                | ||||
|                 // Add it to our temporary active script keeper | ||||
|                 //Scripts.Add(FullScriptID, Script); | ||||
|                 SetScript(ObjectID, ScriptID, Script); | ||||
|                 // We need to give (untrusted) assembly a private instance of BuiltIns | ||||
|                 //  this private copy will contain Read-Only FullScriptID so that it can bring that on to the server whenever needed. | ||||
|                 //OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL_BuiltIn_Commands_Interface LSLB = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL_BuiltIn_Commands_TestImplementation(FullScriptID); | ||||
|                 OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL_BuiltIn_Commands LSLB = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL_BuiltIn_Commands(this, ObjectID); | ||||
| 
 | ||||
|                 // Start the script - giving it BuiltIns | ||||
|                 //myScriptEngine.m_logger.Verbose("ScriptEngine", "ScriptManager initializing script, handing over private builtin command interface"); | ||||
| 
 | ||||
|                 Script.Start(new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL_BuiltIn_Commands(this, ObjectID)); | ||||
|                 Script.Start(LSLB); | ||||
| 
 | ||||
|             } | ||||
|             catch (Exception e) | ||||
|  | @ -210,12 +207,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|             return FileName; | ||||
|         } | ||||
| 
 | ||||
|         //private AppDomain GetFreeAppDomain() | ||||
|         //{ | ||||
|         //    // TODO: Find an available AppDomain - if none, create one and add default security | ||||
|         //    return Thread.GetDomain(); | ||||
|         //} | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Does actual loading and initialization of script Assembly | ||||
|         /// </summary> | ||||
|  | @ -239,68 +230,25 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
|             return mbrt; | ||||
|             //return (LSL_BaseClass)mbrt; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //            //myScriptEngine.m_logger.Verbose("ScriptEngine", "ScriptManager Loading Assembly " + FileName); | ||||
| //            // Load .Net Assembly (.dll) | ||||
| //            // Initialize and return it | ||||
| 
 | ||||
| //            // TODO: Add error handling | ||||
| //            // Script might not follow our rules since users can upload -anything- | ||||
| 
 | ||||
| //            Assembly a; | ||||
| //            //try | ||||
| //            //{ | ||||
| 
 | ||||
| 
 | ||||
| //            // Load to default appdomain (temporary) | ||||
| //            a = Assembly.LoadFrom(FileName); | ||||
| //            // Load to specified appdomain | ||||
| //            // TODO: Insert security | ||||
| //            //a = FreeAppDomain.Load(FileName); | ||||
| //            //} | ||||
| //            //catch (Exception e) | ||||
| //            //{ | ||||
| //            //} | ||||
| 
 | ||||
| 
 | ||||
| //            //foreach (Type _t in a.GetTypes()) | ||||
| //            //{ | ||||
| //            //    Console.WriteLine("Type: " + _t.ToString()); | ||||
| //            //} | ||||
| 
 | ||||
| //            Type t; | ||||
| //            //try | ||||
| //            //{ | ||||
| //            t = a.GetType("SecondLife.Script", true); | ||||
| //            //} | ||||
| //            //catch (Exception e) | ||||
| //            //{ | ||||
| //            //}  | ||||
| 
 | ||||
| //            // Create constructor arguments | ||||
| //            object[] args = new object[] | ||||
| //                { | ||||
| ////                    this,  | ||||
| ////                    host | ||||
| //                }; | ||||
|              | ||||
| //            return (OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass)Activator.CreateInstance(t, args ); | ||||
| 
 | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         internal void ExecuteFunction(IScriptHost ObjectID, string ScriptID, string FunctionName, object[] args) | ||||
|         /// <summary> | ||||
|         /// Execute a LL-event-function in Script | ||||
|         /// </summary> | ||||
|         /// <param name="ObjectID">Object the script is located in</param> | ||||
|         /// <param name="ScriptID">Script ID</param> | ||||
|         /// <param name="FunctionName">Name of function</param> | ||||
|         /// <param name="args">Arguments to pass to function</param> | ||||
|         internal void ExecuteEvent(IScriptHost ObjectID, string ScriptID, string FunctionName, object[] args) | ||||
|         { | ||||
| 
 | ||||
|             // Execute a function in the script | ||||
|             m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function ObjectID: " + ObjectID + ", ScriptID: " + ScriptID + ", FunctionName: " + FunctionName); | ||||
|             OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = m_scriptEngine.myScriptManager.GetScript(ObjectID, ScriptID); | ||||
| 
 | ||||
|             Script.ExecuteEvent(FunctionName, args); | ||||
|             // Must be done in correct AppDomain, so leaving it up to the script itself | ||||
| 
 | ||||
|             Script.Exec.ExecuteEvent(FunctionName, args); | ||||
| 
 | ||||
|             //Type type = Script.GetType(); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Tedd Hansen
						Tedd Hansen