DNE code cleanups

0.6.0-stable
Melanie Thielker 2008-09-26 17:01:33 +00:00
parent e8d1235e91
commit 34cfd710ce
3 changed files with 82 additions and 102 deletions

View File

@ -37,46 +37,37 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
public class AppDomainManager : iScriptEngineFunctionModule public class AppDomainManager : iScriptEngineFunctionModule
{ {
// //
// This class does AppDomain handling and loading/unloading of scripts in it. // This class does AppDomain handling and loading/unloading of
// It is instanced in "ScriptEngine" and controlled from "ScriptManager" // scripts in it. It is instanced in "ScriptEngine" and controlled
// from "ScriptManager"
// //
// 1. Create a new AppDomain if old one is full (or doesn't exist) // 1. Create a new AppDomain if old one is full (or doesn't exist)
// 2. Load scripts into AppDomain // 2. Load scripts into AppDomain
// 3. Unload scripts from AppDomain (stopping them and marking them as inactive) // 3. Unload scripts from AppDomain (stopping them and marking
// them as inactive)
// 4. Unload AppDomain completely when all scripts in it has stopped // 4. Unload AppDomain completely when all scripts in it has stopped
// //
private int maxScriptsPerAppDomain = 1; private int maxScriptsPerAppDomain = 1;
/// <summary> // Internal list of all AppDomains
/// Internal list of all AppDomains private List<AppDomainStructure> appDomains =
/// </summary> new List<AppDomainStructure>();
private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
/// <summary> // Structure to keep track of data around AppDomain
/// Structure to keep track of data around AppDomain
/// </summary>
private class AppDomainStructure private class AppDomainStructure
{ {
/// <summary> // The AppDomain itself
/// The AppDomain itself
/// </summary>
public AppDomain CurrentAppDomain; public AppDomain CurrentAppDomain;
/// <summary> // Number of scripts loaded into AppDomain
/// Number of scripts loaded into AppDomain
/// </summary>
public int ScriptsLoaded; public int ScriptsLoaded;
/// <summary> // Number of dead scripts
/// Number of dead scripts
/// </summary>
public int ScriptsWaitingUnload; public int ScriptsWaitingUnload;
} }
/// <summary> // Current AppDomain
/// Current AppDomain
/// </summary>
private AppDomainStructure currentAD; private AppDomainStructure currentAD;
private object getLock = new object(); // Mutex private object getLock = new object(); // Mutex
@ -92,20 +83,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
public void ReadConfig() public void ReadConfig()
{ {
maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1); maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt(
"ScriptsPerAppDomain", 1);
} }
/// <summary> // Find a free AppDomain, creating one if necessary
/// Find a free AppDomain, creating one if necessary
/// </summary>
/// <returns>Free AppDomain</returns>
private AppDomainStructure GetFreeAppDomain() private AppDomainStructure GetFreeAppDomain()
{ {
// Console.WriteLine("Finding free AppDomain");
lock (getLock) lock (getLock)
{ {
// Current full? // Current full?
if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) if (currentAD != null &&
currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
{ {
// Add it to AppDomains list and empty current // Add it to AppDomains list and empty current
appDomains.Add(currentAD); appDomains.Add(currentAD);
@ -119,21 +108,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
currentAD.CurrentAppDomain = PrepareNewAppDomain(); currentAD.CurrentAppDomain = PrepareNewAppDomain();
} }
// Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
return currentAD; return currentAD;
} }
} }
private int AppDomainNameCount; private int AppDomainNameCount;
/// <summary> // Create and prepare a new AppDomain for scripts
/// 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
AppDomainNameCount++; AppDomainNameCount++;
// TODO: Currently security match current appdomain // TODO: Currently security match current appdomain
// Construct and initialize settings for a second AppDomain. // Construct and initialize settings for a second AppDomain.
@ -143,21 +129,24 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
ads.DisallowCodeDownload = true; ads.DisallowCodeDownload = true;
ads.LoaderOptimization = LoaderOptimization.MultiDomainHost; ads.LoaderOptimization = LoaderOptimization.MultiDomainHost;
ads.ShadowCopyFiles = "false"; // Disable shadowing ads.ShadowCopyFiles = "false"; // Disable shadowing
ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; ads.ConfigurationFile =
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" +
m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain Loading: " + AppDomainNameCount, null, ads);
AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Shared.dll").ToString()); m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName +
AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Shared.dll")); "]: AppDomain Loading: " +
AssemblyName.GetAssemblyName(
"OpenSim.Region.ScriptEngine.Shared.dll").ToString());
AD.Load(AssemblyName.GetAssemblyName(
"OpenSim.Region.ScriptEngine.Shared.dll"));
// Return the new AppDomain // Return the new AppDomain
return AD; return AD;
} }
/// <summary> // Unload appdomains that are full and have only dead scripts
/// Unload appdomains that are full and have only dead scripts
/// </summary>
private void UnloadAppDomains() private void UnloadAppDomains()
{ {
lock (freeLock) lock (freeLock)
@ -174,15 +163,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
{ {
// Remove from internal list // Remove from internal list
appDomains.Remove(ads); appDomains.Remove(ads);
//#if DEBUG
//Console.WriteLine("Found empty AppDomain, unloading");
//long m = GC.GetTotalMemory(true); // This force a garbage collect that freezes some windows plateforms
//#endif
// Unload // Unload
AppDomain.Unload(ads.CurrentAppDomain); AppDomain.Unload(ads.CurrentAppDomain);
//#if DEBUG
//m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory");
//#endif
} }
} }
} }
@ -194,13 +177,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// Find next available AppDomain to put it in // Find next available AppDomain to put it in
AppDomainStructure FreeAppDomain = GetFreeAppDomain(); AppDomainStructure FreeAppDomain = GetFreeAppDomain();
#if DEBUG IScript mbrt = (IScript)
m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Loading into AppDomain: " + FileName); FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(
#endif FileName, "SecondLife.Script");
IScript mbrt =
(IScript)
FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
//Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
FreeAppDomain.ScriptsLoaded++; FreeAppDomain.ScriptsLoaded++;
ad = FreeAppDomain.CurrentAppDomain; ad = FreeAppDomain.CurrentAppDomain;
@ -208,18 +188,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
} }
/// <summary> // Increase "dead script" counter for an AppDomain
/// Increase "dead script" counter for an AppDomain
/// </summary>
/// <param name="ad"></param>
//[Obsolete("Needs fixing, needs a real purpose in life!!!")]
public void StopScript(AppDomain ad) public void StopScript(AppDomain ad)
{ {
lock (freeLock) lock (freeLock)
{ {
#if DEBUG
m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Stopping script in AppDomain");
#endif
// Check if it is current AppDomain // Check if it is current AppDomain
if (currentAD.CurrentAppDomain == ad) if (currentAD.CurrentAppDomain == ad)
{ {
@ -243,9 +216,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
UnloadAppDomains(); // Outsite lock, has its own GetLock UnloadAppDomains(); // Outsite lock, has its own GetLock
} }
/// <summary> // If set to true then threads and stuff should try
/// If set to true then threads and stuff should try to make a graceful exit // to make a graceful exit
/// </summary>
public bool PleaseShutdown public bool PleaseShutdown
{ {
get { return _PleaseShutdown; } get { return _PleaseShutdown; }

View File

@ -29,28 +29,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
{ {
public static class Common public static class Common
{ {
public static bool debug = true;
public static ScriptEngine mySE; public static ScriptEngine mySE;
// This class just contains some static log stuff used for debugging. // This class just contains some static log stuff used for debugging.
//public delegate void SendToDebugEventDelegate(string message);
//public delegate void SendToLogEventDelegate(string message);
//static public event SendToDebugEventDelegate SendToDebugEvent;
//static public event SendToLogEventDelegate SendToLogEvent;
public static void SendToDebug(string message) public static void SendToDebug(string message)
{ {
//if (Debug == true)
mySE.Log.Info("[" + mySE.ScriptEngineName + "]: Debug: " + message); mySE.Log.Info("[" + mySE.ScriptEngineName + "]: Debug: " + message);
//SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message);
} }
public static void SendToLog(string message) public static void SendToLog(string message)
{ {
//if (Debug == true)
mySE.Log.Info("[" + mySE.ScriptEngineName + "]: LOG: " + message); mySE.Log.Info("[" + mySE.ScriptEngineName + "]: LOG: " + message);
//SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message);
} }
} }
} }

View File

@ -44,19 +44,35 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
[Serializable] [Serializable]
public class ScriptEngine : IRegionModule, IEventReceiver, IScriptModule public class ScriptEngine : IRegionModule, IEventReceiver, IScriptModule
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
public static List<ScriptEngine> ScriptEngines =
new List<ScriptEngine>();
public static List<ScriptEngine> ScriptEngines = new List<ScriptEngine>();
private Scene m_Scene; private Scene m_Scene;
public Scene World public Scene World
{ {
get { return m_Scene; } get { return m_Scene; }
} }
public EventManager m_EventManager; // Handles and queues incoming events from OpenSim
public EventQueueManager m_EventQueueManager; // Executes events, handles script threads // Handles and queues incoming events from OpenSim
public ScriptManager m_ScriptManager; // Load, unload and execute scripts public EventManager m_EventManager;
public AppDomainManager m_AppDomainManager; // Handles loading/unloading of scripts into AppDomains
public static MaintenanceThread m_MaintenanceThread; // Thread that does different kinds of maintenance, for example refreshing config and killing scripts that has been running too long // Executes events, handles script threads
public EventQueueManager m_EventQueueManager;
// Load, unload and execute scripts
public ScriptManager m_ScriptManager;
// Handles loading/unloading of scripts into AppDomains
public AppDomainManager m_AppDomainManager;
// Thread that does different kinds of maintenance,
// for example refreshing config and killing scripts
// that has been running too long
public static MaintenanceThread m_MaintenanceThread;
public IConfigSource ConfigSource; public IConfigSource ConfigSource;
public IConfig ScriptConfigSource; public IConfig ScriptConfigSource;
@ -67,13 +83,13 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
get { return ScriptConfigSource; } get { return ScriptConfigSource; }
} }
/// <summary> // How many seconds between re-reading config-file.
/// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. // 0 = never. ScriptEngine will try to adjust to new config changes.
/// </summary>
public int RefreshConfigFileSeconds { public int RefreshConfigFileSeconds {
get { return (int)(RefreshConfigFilens / 10000000); } get { return (int)(RefreshConfigFilens / 10000000); }
set { RefreshConfigFilens = value * 10000000; } set { RefreshConfigFilens = value * 10000000; }
} }
public long RefreshConfigFilens; public long RefreshConfigFilens;
public string ScriptEngineName public string ScriptEngineName
@ -88,10 +104,14 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
public ScriptEngine() public ScriptEngine()
{ {
Common.mySE = this; // For logging, just need any instance, doesn't matter // For logging, just need any instance, doesn't matter
Common.mySE = this;
lock (ScriptEngines) lock (ScriptEngines)
{ {
ScriptEngines.Add(this); // Keep a list of ScriptEngines for shared threads to process all instances // Keep a list of ScriptEngines for shared threads
// to process all instances
ScriptEngines.Add(this);
} }
} }
@ -105,17 +125,17 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// Make sure we have config // Make sure we have config
if (ConfigSource.Configs[ScriptEngineName] == null) if (ConfigSource.Configs[ScriptEngineName] == null)
ConfigSource.AddConfig(ScriptEngineName); ConfigSource.AddConfig(ScriptEngineName);
ScriptConfigSource = ConfigSource.Configs[ScriptEngineName]; ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
m_enabled = ScriptConfigSource.GetBoolean("Enabled", true); m_enabled = ScriptConfigSource.GetBoolean("Enabled", true);
if (!m_enabled) if (!m_enabled)
return; return;
//m_log.Info("[" + ScriptEngineName + "]: InitializeEngine");
// Create all objects we'll be using // Create all objects we'll be using
m_EventQueueManager = new EventQueueManager(this); m_EventQueueManager = new EventQueueManager(this);
m_EventManager = new EventManager(this, true); m_EventManager = new EventManager(this, true);
// We need to start it // We need to start it
m_ScriptManager = new ScriptManager(this); m_ScriptManager = new ScriptManager(this);
m_ScriptManager.Setup(); m_ScriptManager.Setup();
@ -123,7 +143,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
if (m_MaintenanceThread == null) if (m_MaintenanceThread == null)
m_MaintenanceThread = new MaintenanceThread(); m_MaintenanceThread = new MaintenanceThread();
m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\""); m_log.Info("[" + ScriptEngineName + "]: Reading configuration "+
"from config section \"" + ScriptEngineName + "\"");
ReadConfig(); ReadConfig();
m_Scene.StackModuleInterface<IScriptModule>(this); m_Scene.StackModuleInterface<IScriptModule>(this);
@ -155,15 +177,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
public void ReadConfig() public void ReadConfig()
{ {
#if DEBUG
//m_log.Debug("[" + ScriptEngineName + "]: Refreshing configuration for all modules");
#endif
RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30); RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30);
// Create a new object (probably not necessary?)
// ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig(); if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig();
if (m_EventManager != null) m_EventManager.ReadConfig(); if (m_EventManager != null) m_EventManager.ReadConfig();
if (m_ScriptManager != null) m_ScriptManager.ReadConfig(); if (m_ScriptManager != null) m_ScriptManager.ReadConfig();
@ -189,13 +204,15 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
public bool PostObjectEvent(uint localID, EventParams p) public bool PostObjectEvent(uint localID, EventParams p)
{ {
return m_EventQueueManager.AddToObjectQueue(localID, p.EventName, p.DetectParams, p.Params); return m_EventQueueManager.AddToObjectQueue(localID, p.EventName,
p.DetectParams, p.Params);
} }
public bool PostScriptEvent(UUID itemID, EventParams p) public bool PostScriptEvent(UUID itemID, EventParams p)
{ {
uint localID = m_ScriptManager.GetLocalID(itemID); uint localID = m_ScriptManager.GetLocalID(itemID);
return m_EventQueueManager.AddToScriptQueue(localID, itemID, p.EventName, p.DetectParams, p.Params); return m_EventQueueManager.AddToScriptQueue(localID, itemID,
p.EventName, p.DetectParams, p.Params);
} }
public DetectParams GetDetectParams(UUID itemID, int number) public DetectParams GetDetectParams(UUID itemID, int number)
@ -341,7 +358,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
id.Running = false; id.Running = false;
} }
public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) public void OnGetScriptRunning(IClientAPI controllingClient,
UUID objectID, UUID itemID)
{ {
uint localID = m_ScriptManager.GetLocalID(itemID); uint localID = m_ScriptManager.GetLocalID(itemID);
if (localID == 0) if (localID == 0)