From 37446b0392ba423894952f81aa0f938d2bd2de22 Mon Sep 17 00:00:00 2001
From: Tedd Hansen
Date: Sat, 18 Aug 2007 23:24:38 +0000
Subject: 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).
---
OpenSim/Region/ScriptEngine/Common/Executor.cs | 48 ++++++++++++-
.../Common/LSL_BuiltIn_Commands_Interface.cs | 1 +
.../ScriptEngine/DotNetEngine/AppDomainManager.cs | 66 ++++++++----------
.../DotNetEngine/Compiler/LSL/LSL_BaseClass.cs | 38 +++-------
.../Compiler/Server_API/LSL_BuiltIn_Commands.cs | 7 +-
.../ScriptEngine/DotNetEngine/EventQueueManager.cs | 2 +-
.../ScriptEngine/DotNetEngine/ScriptEngine.cs | 2 +-
.../ScriptEngine/DotNetEngine/ScriptManager.cs | 80 ++++------------------
8 files changed, 107 insertions(+), 137 deletions(-)
diff --git a/OpenSim/Region/ScriptEngine/Common/Executor.cs b/OpenSim/Region/ScriptEngine/Common/Executor.cs
index 2ae6a60..ca6459b 100644
--- a/OpenSim/Region/ScriptEngine/Common/Executor.cs
+++ b/OpenSim/Region/ScriptEngine/Common/Executor.cs
@@ -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());
+ }
+
+
+ }
+
+
}
}
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs
index beddbc5..f80898b 100644
--- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs
+++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs
@@ -34,6 +34,7 @@ namespace OpenSim.Region.ScriptEngine.Common
{
public interface LSL_BuiltIn_Commands_Interface
{
+
string State();
double llSin(double f);
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
index f80ebac..33e95d3 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
@@ -12,9 +12,12 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
{
private int MaxScriptsPerAppDomain = 1;
///
- /// List of all AppDomains
+ /// Internal list of all AppDomains
///
private List AppDomains = new List();
+ ///
+ /// Structure to keep track of data around AppDomain
+ ///
private struct AppDomainStructure
{
///
@@ -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;
}
///
@@ -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
}
+
}
}
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs
index 7334e6f..bfb8913 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs
@@ -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());
- }
-
-
- }
-
//
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
index 297a45c..8982bb6 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
@@ -16,6 +16,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
///
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);
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
index c20a8b0..311d32b 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
@@ -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);
}
}
}
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
index d08fc32..9b8cff0 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
@@ -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?
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
index 602ac9f..926ec74 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
///
/// Loads scripts
/// Compiles them if necessary
- /// Execute functions for EventQueueManager
+ /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
///
[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();
- //}
-
///
/// Does actual loading and initialization of script Assembly
///
@@ -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)
+ ///
+ /// Execute a LL-event-function in Script
+ ///
+ /// Object the script is located in
+ /// Script ID
+ /// Name of function
+ /// Arguments to pass to function
+ 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();
--
cgit v1.1