diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs index 7941ea2e59..f80ebac2ea 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs @@ -10,7 +10,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine { public class AppDomainManager { - private int MaxScriptsPerAppDomain = 10; + private int MaxScriptsPerAppDomain = 1; + /// + /// List of all AppDomains + /// private List AppDomains = new List(); private struct AppDomainStructure { @@ -27,8 +30,12 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine /// public int ScriptsWaitingUnload; } + /// + /// Current AppDomain + /// private AppDomainStructure CurrentAD; - private object GetLock = new object(); + private object GetLock = new object(); // Mutex + private object FreeLock = new object(); // Mutex private ScriptEngine m_scriptEngine; public AppDomainManager(ScriptEngine scriptEngine) @@ -36,17 +43,28 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine m_scriptEngine = scriptEngine; } + /// + /// Find a free AppDomain, creating one if necessary + /// + /// Free AppDomain internal AppDomain GetFreeAppDomain() { + FreeAppDomains(); lock(GetLock) { - // No current or current full? - if (CurrentAD.CurrentAppDomain == null || CurrentAD.ScriptsLoaded >= MaxScriptsPerAppDomain) + // Current full? + if (CurrentAD.ScriptsLoaded >= MaxScriptsPerAppDomain) + { + AppDomains.Add(CurrentAD); + CurrentAD = new AppDomainStructure(); + } + // No current + if (CurrentAD.CurrentAppDomain == null) { // Create a new current AppDomain CurrentAD = new AppDomainStructure(); CurrentAD.ScriptsWaitingUnload = 0; // to avoid compile warning for not in use CurrentAD.CurrentAppDomain = PrepareNewAppDomain(); - AppDomains.Add(CurrentAD); + } @@ -58,6 +76,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine } private int AppDomainNameCount; + /// + /// Create and prepare a new AppDomain for scripts + /// + /// The new AppDomain private AppDomain PrepareNewAppDomain() { // Create and prepare a new AppDomain @@ -80,20 +102,20 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine 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)); + //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"); - } + // } + // catch (Exception e) + // { + // //Console.WriteLine("FAILED load"); + // } - } + //} //Console.WriteLine("Assembly file: " + this.GetType().Assembly.CodeBase); //Console.WriteLine("Assembly name: " + this.GetType().ToString()); @@ -106,5 +128,55 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine } + /// + /// Unload appdomains that are full and have only dead scripts + /// + private void FreeAppDomains() + { + lock (FreeLock) + { + foreach (AppDomainStructure ads in new System.Collections.ArrayList(AppDomains)) + { + if (ads.CurrentAppDomain != CurrentAD.CurrentAppDomain) + { + // Not current AppDomain + if (ads.ScriptsLoaded == ads.ScriptsWaitingUnload) + { + AppDomains.Remove(ads); + AppDomain.Unload(ads.CurrentAppDomain); + } + } + } // foreach + } // lock + } + + /// + /// Increase "dead script" counter for an AppDomain + /// + /// + [Obsolete("Needs optimizing!!!")] + public void StopScriptInAppDomain(AppDomain ad) + { + lock (FreeLock) + { + if (CurrentAD.CurrentAppDomain == ad) + { + CurrentAD.ScriptsWaitingUnload++; + return; + } + + foreach (AppDomainStructure ads in new System.Collections.ArrayList(AppDomains)) + { + if (ads.CurrentAppDomain == ad) + { + AppDomainStructure ads2 = ads; + ads2.ScriptsWaitingUnload++; + AppDomains.Remove(ads); + AppDomains.Add(ads2); + return; + } + } // foreach + } // lock + } } }