Added (theoretical) AppDomain cleanup code.

afrisby
Tedd Hansen 2007-08-18 22:33:06 +00:00
parent 240712ca9f
commit 1ae73931da
1 changed files with 89 additions and 17 deletions

View File

@ -10,7 +10,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
{ {
public class AppDomainManager public class AppDomainManager
{ {
private int MaxScriptsPerAppDomain = 10; private int MaxScriptsPerAppDomain = 1;
/// <summary>
/// List of all AppDomains
/// </summary>
private List<AppDomainStructure> AppDomains = new List<AppDomainStructure>(); private List<AppDomainStructure> AppDomains = new List<AppDomainStructure>();
private struct AppDomainStructure private struct AppDomainStructure
{ {
@ -27,8 +30,12 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
/// </summary> /// </summary>
public int ScriptsWaitingUnload; public int ScriptsWaitingUnload;
} }
/// <summary>
/// Current AppDomain
/// </summary>
private AppDomainStructure CurrentAD; private AppDomainStructure CurrentAD;
private object GetLock = new object(); private object GetLock = new object(); // Mutex
private object FreeLock = new object(); // Mutex
private ScriptEngine m_scriptEngine; private ScriptEngine m_scriptEngine;
public AppDomainManager(ScriptEngine scriptEngine) public AppDomainManager(ScriptEngine scriptEngine)
@ -36,17 +43,28 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
m_scriptEngine = scriptEngine; m_scriptEngine = scriptEngine;
} }
/// <summary>
/// Find a free AppDomain, creating one if necessary
/// </summary>
/// <returns>Free AppDomain</returns>
internal AppDomain GetFreeAppDomain() internal AppDomain GetFreeAppDomain()
{ {
FreeAppDomains();
lock(GetLock) { lock(GetLock) {
// No current or current full? // Current full?
if (CurrentAD.CurrentAppDomain == null || CurrentAD.ScriptsLoaded >= MaxScriptsPerAppDomain) if (CurrentAD.ScriptsLoaded >= MaxScriptsPerAppDomain)
{
AppDomains.Add(CurrentAD);
CurrentAD = new AppDomainStructure();
}
// No current
if (CurrentAD.CurrentAppDomain == null)
{ {
// Create a new current AppDomain // Create a new current AppDomain
CurrentAD = new AppDomainStructure(); CurrentAD = new AppDomainStructure();
CurrentAD.ScriptsWaitingUnload = 0; // to avoid compile warning for not in use CurrentAD.ScriptsWaitingUnload = 0; // to avoid compile warning for not in use
CurrentAD.CurrentAppDomain = PrepareNewAppDomain(); CurrentAD.CurrentAppDomain = PrepareNewAppDomain();
AppDomains.Add(CurrentAD);
} }
@ -58,6 +76,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
} }
private int AppDomainNameCount; private int AppDomainNameCount;
/// <summary>
/// Create and prepare a new AppDomain for scripts
/// </summary>
/// <returns>The new AppDomain</returns>
private AppDomain PrepareNewAppDomain() private AppDomain PrepareNewAppDomain()
{ {
// Create and prepare a new AppDomain // Create and prepare a new AppDomain
@ -80,20 +102,20 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) //foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{ //{
//Console.WriteLine("Loading: " + a.GetName(true)); // //Console.WriteLine("Loading: " + a.GetName(true));
try // try
{ // {
//AD.Load(a.GetName(true)); // //AD.Load(a.GetName(true));
} // }
catch (Exception e) // catch (Exception e)
{ // {
//Console.WriteLine("FAILED load"); // //Console.WriteLine("FAILED load");
} // }
} //}
//Console.WriteLine("Assembly file: " + this.GetType().Assembly.CodeBase); //Console.WriteLine("Assembly file: " + this.GetType().Assembly.CodeBase);
//Console.WriteLine("Assembly name: " + this.GetType().ToString()); //Console.WriteLine("Assembly name: " + this.GetType().ToString());
@ -106,5 +128,55 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
} }
/// <summary>
/// Unload appdomains that are full and have only dead scripts
/// </summary>
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
}
/// <summary>
/// Increase "dead script" counter for an AppDomain
/// </summary>
/// <param name="ad"></param>
[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
}
} }
} }