From 6dd923b01d6864ffcb17030c9de17224f45b4c2a Mon Sep 17 00:00:00 2001
From: Tedd Hansen
Date: Fri, 5 Oct 2007 19:56:44 +0000
Subject: Some more work on new ScriptEngine.
---
.../ScriptEngine/DotNetEngine/AppDomainManager.cs | 200 +++++++++++++++++++++
1 file changed, 200 insertions(+)
create mode 100644 OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs
(limited to 'OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs')
diff --git a/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs
new file mode 100644
index 0000000..9829c1d
--- /dev/null
+++ b/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs
@@ -0,0 +1,200 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+using System.Threading;
+using System.Runtime.Remoting;
+using System.IO;
+using OpenSim.Region.Environment.Scenes;
+using OpenSim.Region.Environment.Scenes.Scripting;
+using OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL;
+using OpenSim.Region.ScriptEngine.Common;
+using libsecondlife;
+
+namespace OpenSim.Grid.ScriptEngine.DotNetEngine
+{
+ public class AppDomainManager
+ {
+ private int maxScriptsPerAppDomain = 1;
+ ///
+ /// Internal list of all AppDomains
+ ///
+ private List appDomains = new List();
+ ///
+ /// Structure to keep track of data around AppDomain
+ ///
+ private class AppDomainStructure
+ {
+ ///
+ /// The AppDomain itself
+ ///
+ public AppDomain CurrentAppDomain;
+ ///
+ /// Number of scripts loaded into AppDomain
+ ///
+ public int ScriptsLoaded;
+ ///
+ /// Number of dead scripts
+ ///
+ public int ScriptsWaitingUnload;
+ }
+ ///
+ /// Current AppDomain
+ ///
+ private AppDomainStructure currentAD;
+ private object getLock = new object(); // Mutex
+ private object freeLock = new object(); // Mutex
+
+ //private ScriptEngine m_scriptEngine;
+ //public AppDomainManager(ScriptEngine scriptEngine)
+ public AppDomainManager()
+ {
+ //m_scriptEngine = scriptEngine;
+ }
+
+ ///
+ /// Find a free AppDomain, creating one if necessary
+ ///
+ /// Free AppDomain
+ private AppDomainStructure GetFreeAppDomain()
+ {
+ Console.WriteLine("Finding free AppDomain");
+ lock (getLock)
+ {
+ // Current full?
+ if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
+ {
+ // Add it to AppDomains list and empty current
+ appDomains.Add(currentAD);
+ currentAD = null;
+ }
+ // No current
+ if (currentAD == null)
+ {
+ // Create a new current AppDomain
+ currentAD = new AppDomainStructure();
+ currentAD.CurrentAppDomain = PrepareNewAppDomain();
+ }
+
+ Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
+ return currentAD;
+ } // lock
+ }
+
+ private int AppDomainNameCount;
+ ///
+ /// Create and prepare a new AppDomain for scripts
+ ///
+ /// The new AppDomain
+ private AppDomain PrepareNewAppDomain()
+ {
+ // Create and prepare a new AppDomain
+ AppDomainNameCount++;
+ // TODO: Currently security match current appdomain
+
+ // Construct and initialize settings for a second AppDomain.
+ AppDomainSetup ads = new AppDomainSetup();
+ ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
+ ads.DisallowBindingRedirects = false;
+ ads.DisallowCodeDownload = true;
+ ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;)
+ ads.ShadowCopyFiles = "true"; // Enabled shadowing
+ ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
+
+ AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
+ Console.WriteLine("Loading: " + AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString());
+ AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll"));
+
+ // Return the new AppDomain
+ return AD;
+
+ }
+
+ ///
+ /// Unload appdomains that are full and have only dead scripts
+ ///
+ private void UnloadAppDomains()
+ {
+ 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
+ // Is number of unloaded bigger or equal to number of loaded?
+ if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload)
+ {
+ Console.WriteLine("Found empty AppDomain, unloading");
+ // Remove from internal list
+ appDomains.Remove(ads);
+#if DEBUG
+ long m = GC.GetTotalMemory(true);
+#endif
+ // Unload
+ AppDomain.Unload(ads.CurrentAppDomain);
+#if DEBUG
+ Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory");
+#endif
+ }
+ }
+ } // foreach
+ } // lock
+ }
+
+
+
+ public OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass LoadScript(string FileName)
+ {
+ // Find next available AppDomain to put it in
+ AppDomainStructure FreeAppDomain = GetFreeAppDomain();
+
+ Console.WriteLine("Loading into AppDomain: " + FileName);
+ LSL_BaseClass mbrt = (LSL_BaseClass)FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
+ //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
+ FreeAppDomain.ScriptsLoaded++;
+
+ return mbrt;
+ }
+
+
+ ///
+ /// Increase "dead script" counter for an AppDomain
+ ///
+ ///
+ //[Obsolete("Needs fixing, needs a real purpose in life!!!")]
+ public void StopScript(AppDomain ad)
+ {
+ lock (freeLock)
+ {
+ Console.WriteLine("Stopping script in AppDomain");
+ // 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
+ ads.ScriptsWaitingUnload++;
+ break;
+ }
+ } // foreach
+ } // lock
+
+ UnloadAppDomains(); // Outsite lock, has its own GetLock
+
+
+ }
+
+
+ }
+}
--
cgit v1.1