aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs106
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs68
3 files changed, 82 insertions, 102 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
index 5a77d39..da461e3 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
@@ -37,46 +37,37 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
37 public class AppDomainManager : iScriptEngineFunctionModule 37 public class AppDomainManager : iScriptEngineFunctionModule
38 { 38 {
39 // 39 //
40 // This class does AppDomain handling and loading/unloading of scripts in it. 40 // This class does AppDomain handling and loading/unloading of
41 // It is instanced in "ScriptEngine" and controlled from "ScriptManager" 41 // scripts in it. It is instanced in "ScriptEngine" and controlled
42 // from "ScriptManager"
42 // 43 //
43 // 1. Create a new AppDomain if old one is full (or doesn't exist) 44 // 1. Create a new AppDomain if old one is full (or doesn't exist)
44 // 2. Load scripts into AppDomain 45 // 2. Load scripts into AppDomain
45 // 3. Unload scripts from AppDomain (stopping them and marking them as inactive) 46 // 3. Unload scripts from AppDomain (stopping them and marking
47 // them as inactive)
46 // 4. Unload AppDomain completely when all scripts in it has stopped 48 // 4. Unload AppDomain completely when all scripts in it has stopped
47 // 49 //
48 50
49 private int maxScriptsPerAppDomain = 1; 51 private int maxScriptsPerAppDomain = 1;
50 52
51 /// <summary> 53 // Internal list of all AppDomains
52 /// Internal list of all AppDomains 54 private List<AppDomainStructure> appDomains =
53 /// </summary> 55 new List<AppDomainStructure>();
54 private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
55 56
56 /// <summary> 57 // Structure to keep track of data around AppDomain
57 /// Structure to keep track of data around AppDomain
58 /// </summary>
59 private class AppDomainStructure 58 private class AppDomainStructure
60 { 59 {
61 /// <summary> 60 // The AppDomain itself
62 /// The AppDomain itself
63 /// </summary>
64 public AppDomain CurrentAppDomain; 61 public AppDomain CurrentAppDomain;
65 62
66 /// <summary> 63 // Number of scripts loaded into AppDomain
67 /// Number of scripts loaded into AppDomain
68 /// </summary>
69 public int ScriptsLoaded; 64 public int ScriptsLoaded;
70 65
71 /// <summary> 66 // Number of dead scripts
72 /// Number of dead scripts
73 /// </summary>
74 public int ScriptsWaitingUnload; 67 public int ScriptsWaitingUnload;
75 } 68 }
76 69
77 /// <summary> 70 // Current AppDomain
78 /// Current AppDomain
79 /// </summary>
80 private AppDomainStructure currentAD; 71 private AppDomainStructure currentAD;
81 72
82 private object getLock = new object(); // Mutex 73 private object getLock = new object(); // Mutex
@@ -92,20 +83,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
92 83
93 public void ReadConfig() 84 public void ReadConfig()
94 { 85 {
95 maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1); 86 maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt(
87 "ScriptsPerAppDomain", 1);
96 } 88 }
97 89
98 /// <summary> 90 // Find a free AppDomain, creating one if necessary
99 /// Find a free AppDomain, creating one if necessary
100 /// </summary>
101 /// <returns>Free AppDomain</returns>
102 private AppDomainStructure GetFreeAppDomain() 91 private AppDomainStructure GetFreeAppDomain()
103 { 92 {
104 // Console.WriteLine("Finding free AppDomain");
105 lock (getLock) 93 lock (getLock)
106 { 94 {
107 // Current full? 95 // Current full?
108 if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) 96 if (currentAD != null &&
97 currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
109 { 98 {
110 // Add it to AppDomains list and empty current 99 // Add it to AppDomains list and empty current
111 appDomains.Add(currentAD); 100 appDomains.Add(currentAD);
@@ -119,21 +108,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
119 currentAD.CurrentAppDomain = PrepareNewAppDomain(); 108 currentAD.CurrentAppDomain = PrepareNewAppDomain();
120 } 109 }
121 110
122 // Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
123 return currentAD; 111 return currentAD;
124 } 112 }
125 } 113 }
126 114
127 private int AppDomainNameCount; 115 private int AppDomainNameCount;
128 116
129 /// <summary> 117 // Create and prepare a new AppDomain for scripts
130 /// Create and prepare a new AppDomain for scripts
131 /// </summary>
132 /// <returns>The new AppDomain</returns>
133 private AppDomain PrepareNewAppDomain() 118 private AppDomain PrepareNewAppDomain()
134 { 119 {
135 // Create and prepare a new AppDomain 120 // Create and prepare a new AppDomain
136 AppDomainNameCount++; 121 AppDomainNameCount++;
122
137 // TODO: Currently security match current appdomain 123 // TODO: Currently security match current appdomain
138 124
139 // Construct and initialize settings for a second AppDomain. 125 // Construct and initialize settings for a second AppDomain.
@@ -143,21 +129,24 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
143 ads.DisallowCodeDownload = true; 129 ads.DisallowCodeDownload = true;
144 ads.LoaderOptimization = LoaderOptimization.MultiDomainHost; 130 ads.LoaderOptimization = LoaderOptimization.MultiDomainHost;
145 ads.ShadowCopyFiles = "false"; // Disable shadowing 131 ads.ShadowCopyFiles = "false"; // Disable shadowing
146 ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; 132 ads.ConfigurationFile =
133 AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
147 134
148 135
149 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); 136 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" +
150 m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain Loading: " + 137 AppDomainNameCount, null, ads);
151 AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Shared.dll").ToString()); 138 m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName +
152 AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Shared.dll")); 139 "]: AppDomain Loading: " +
140 AssemblyName.GetAssemblyName(
141 "OpenSim.Region.ScriptEngine.Shared.dll").ToString());
142 AD.Load(AssemblyName.GetAssemblyName(
143 "OpenSim.Region.ScriptEngine.Shared.dll"));
153 144
154 // Return the new AppDomain 145 // Return the new AppDomain
155 return AD; 146 return AD;
156 } 147 }
157 148
158 /// <summary> 149 // Unload appdomains that are full and have only dead scripts
159 /// Unload appdomains that are full and have only dead scripts
160 /// </summary>
161 private void UnloadAppDomains() 150 private void UnloadAppDomains()
162 { 151 {
163 lock (freeLock) 152 lock (freeLock)
@@ -174,15 +163,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
174 { 163 {
175 // Remove from internal list 164 // Remove from internal list
176 appDomains.Remove(ads); 165 appDomains.Remove(ads);
177//#if DEBUG 166
178 //Console.WriteLine("Found empty AppDomain, unloading");
179 //long m = GC.GetTotalMemory(true); // This force a garbage collect that freezes some windows plateforms
180//#endif
181 // Unload 167 // Unload
182 AppDomain.Unload(ads.CurrentAppDomain); 168 AppDomain.Unload(ads.CurrentAppDomain);
183//#if DEBUG
184 //m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory");
185//#endif
186 } 169 }
187 } 170 }
188 } 171 }
@@ -194,13 +177,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
194 // Find next available AppDomain to put it in 177 // Find next available AppDomain to put it in
195 AppDomainStructure FreeAppDomain = GetFreeAppDomain(); 178 AppDomainStructure FreeAppDomain = GetFreeAppDomain();
196 179
197#if DEBUG 180 IScript mbrt = (IScript)
198 m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Loading into AppDomain: " + FileName); 181 FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(
199#endif 182 FileName, "SecondLife.Script");
200 IScript mbrt = 183
201 (IScript)
202 FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
203 //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
204 FreeAppDomain.ScriptsLoaded++; 184 FreeAppDomain.ScriptsLoaded++;
205 ad = FreeAppDomain.CurrentAppDomain; 185 ad = FreeAppDomain.CurrentAppDomain;
206 186
@@ -208,18 +188,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
208 } 188 }
209 189
210 190
211 /// <summary> 191 // Increase "dead script" counter for an AppDomain
212 /// Increase "dead script" counter for an AppDomain
213 /// </summary>
214 /// <param name="ad"></param>
215 //[Obsolete("Needs fixing, needs a real purpose in life!!!")]
216 public void StopScript(AppDomain ad) 192 public void StopScript(AppDomain ad)
217 { 193 {
218 lock (freeLock) 194 lock (freeLock)
219 { 195 {
220#if DEBUG
221 m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Stopping script in AppDomain");
222#endif
223 // Check if it is current AppDomain 196 // Check if it is current AppDomain
224 if (currentAD.CurrentAppDomain == ad) 197 if (currentAD.CurrentAppDomain == ad)
225 { 198 {
@@ -243,9 +216,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
243 UnloadAppDomains(); // Outsite lock, has its own GetLock 216 UnloadAppDomains(); // Outsite lock, has its own GetLock
244 } 217 }
245 218
246 /// <summary> 219 // If set to true then threads and stuff should try
247 /// If set to true then threads and stuff should try to make a graceful exit 220 // to make a graceful exit
248 /// </summary>
249 public bool PleaseShutdown 221 public bool PleaseShutdown
250 { 222 {
251 get { return _PleaseShutdown; } 223 get { return _PleaseShutdown; }
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs
index 3d9e19b..56b4c8e 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs
@@ -29,28 +29,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
29{ 29{
30 public static class Common 30 public static class Common
31 { 31 {
32 public static bool debug = true;
33 public static ScriptEngine mySE; 32 public static ScriptEngine mySE;
34 33
35 // This class just contains some static log stuff used for debugging. 34 // This class just contains some static log stuff used for debugging.
36 35
37 //public delegate void SendToDebugEventDelegate(string message);
38 //public delegate void SendToLogEventDelegate(string message);
39 //static public event SendToDebugEventDelegate SendToDebugEvent;
40 //static public event SendToLogEventDelegate SendToLogEvent;
41
42 public static void SendToDebug(string message) 36 public static void SendToDebug(string message)
43 { 37 {
44 //if (Debug == true)
45 mySE.Log.Info("[" + mySE.ScriptEngineName + "]: Debug: " + message); 38 mySE.Log.Info("[" + mySE.ScriptEngineName + "]: Debug: " + message);
46 //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message);
47 } 39 }
48 40
49 public static void SendToLog(string message) 41 public static void SendToLog(string message)
50 { 42 {
51 //if (Debug == true)
52 mySE.Log.Info("[" + mySE.ScriptEngineName + "]: LOG: " + message); 43 mySE.Log.Info("[" + mySE.ScriptEngineName + "]: LOG: " + message);
53 //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message);
54 } 44 }
55 } 45 }
56} 46}
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
index 71db4ee..ee64c41 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
@@ -44,19 +44,35 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
44 [Serializable] 44 [Serializable]
45 public class ScriptEngine : IRegionModule, IEventReceiver, IScriptModule 45 public class ScriptEngine : IRegionModule, IEventReceiver, IScriptModule
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log =
48 LogManager.GetLogger(
49 MethodBase.GetCurrentMethod().DeclaringType);
50
51 public static List<ScriptEngine> ScriptEngines =
52 new List<ScriptEngine>();
48 53
49 public static List<ScriptEngine> ScriptEngines = new List<ScriptEngine>();
50 private Scene m_Scene; 54 private Scene m_Scene;
51 public Scene World 55 public Scene World
52 { 56 {
53 get { return m_Scene; } 57 get { return m_Scene; }
54 } 58 }
55 public EventManager m_EventManager; // Handles and queues incoming events from OpenSim 59
56 public EventQueueManager m_EventQueueManager; // Executes events, handles script threads 60 // Handles and queues incoming events from OpenSim
57 public ScriptManager m_ScriptManager; // Load, unload and execute scripts 61 public EventManager m_EventManager;
58 public AppDomainManager m_AppDomainManager; // Handles loading/unloading of scripts into AppDomains 62
59 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 63 // Executes events, handles script threads
64 public EventQueueManager m_EventQueueManager;
65
66 // Load, unload and execute scripts
67 public ScriptManager m_ScriptManager;
68
69 // Handles loading/unloading of scripts into AppDomains
70 public AppDomainManager m_AppDomainManager;
71
72 // Thread that does different kinds of maintenance,
73 // for example refreshing config and killing scripts
74 // that has been running too long
75 public static MaintenanceThread m_MaintenanceThread;
60 76
61 public IConfigSource ConfigSource; 77 public IConfigSource ConfigSource;
62 public IConfig ScriptConfigSource; 78 public IConfig ScriptConfigSource;
@@ -67,13 +83,13 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
67 get { return ScriptConfigSource; } 83 get { return ScriptConfigSource; }
68 } 84 }
69 85
70 /// <summary> 86 // How many seconds between re-reading config-file.
71 /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. 87 // 0 = never. ScriptEngine will try to adjust to new config changes.
72 /// </summary>
73 public int RefreshConfigFileSeconds { 88 public int RefreshConfigFileSeconds {
74 get { return (int)(RefreshConfigFilens / 10000000); } 89 get { return (int)(RefreshConfigFilens / 10000000); }
75 set { RefreshConfigFilens = value * 10000000; } 90 set { RefreshConfigFilens = value * 10000000; }
76 } 91 }
92
77 public long RefreshConfigFilens; 93 public long RefreshConfigFilens;
78 94
79 public string ScriptEngineName 95 public string ScriptEngineName
@@ -88,10 +104,14 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
88 104
89 public ScriptEngine() 105 public ScriptEngine()
90 { 106 {
91 Common.mySE = this; // For logging, just need any instance, doesn't matter 107 // For logging, just need any instance, doesn't matter
108 Common.mySE = this;
109
92 lock (ScriptEngines) 110 lock (ScriptEngines)
93 { 111 {
94 ScriptEngines.Add(this); // Keep a list of ScriptEngines for shared threads to process all instances 112 // Keep a list of ScriptEngines for shared threads
113 // to process all instances
114 ScriptEngines.Add(this);
95 } 115 }
96 } 116 }
97 117
@@ -105,17 +125,17 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
105 // Make sure we have config 125 // Make sure we have config
106 if (ConfigSource.Configs[ScriptEngineName] == null) 126 if (ConfigSource.Configs[ScriptEngineName] == null)
107 ConfigSource.AddConfig(ScriptEngineName); 127 ConfigSource.AddConfig(ScriptEngineName);
128
108 ScriptConfigSource = ConfigSource.Configs[ScriptEngineName]; 129 ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
109 130
110 m_enabled = ScriptConfigSource.GetBoolean("Enabled", true); 131 m_enabled = ScriptConfigSource.GetBoolean("Enabled", true);
111 if (!m_enabled) 132 if (!m_enabled)
112 return; 133 return;
113 134
114 //m_log.Info("[" + ScriptEngineName + "]: InitializeEngine");
115
116 // Create all objects we'll be using 135 // Create all objects we'll be using
117 m_EventQueueManager = new EventQueueManager(this); 136 m_EventQueueManager = new EventQueueManager(this);
118 m_EventManager = new EventManager(this, true); 137 m_EventManager = new EventManager(this, true);
138
119 // We need to start it 139 // We need to start it
120 m_ScriptManager = new ScriptManager(this); 140 m_ScriptManager = new ScriptManager(this);
121 m_ScriptManager.Setup(); 141 m_ScriptManager.Setup();
@@ -123,7 +143,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
123 if (m_MaintenanceThread == null) 143 if (m_MaintenanceThread == null)
124 m_MaintenanceThread = new MaintenanceThread(); 144 m_MaintenanceThread = new MaintenanceThread();
125 145
126 m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\""); 146 m_log.Info("[" + ScriptEngineName + "]: Reading configuration "+
147 "from config section \"" + ScriptEngineName + "\"");
148
127 ReadConfig(); 149 ReadConfig();
128 150
129 m_Scene.StackModuleInterface<IScriptModule>(this); 151 m_Scene.StackModuleInterface<IScriptModule>(this);
@@ -155,15 +177,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
155 177
156 public void ReadConfig() 178 public void ReadConfig()
157 { 179 {
158#if DEBUG
159 //m_log.Debug("[" + ScriptEngineName + "]: Refreshing configuration for all modules");
160#endif
161 RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30); 180 RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30);
162 181
163
164 // Create a new object (probably not necessary?)
165// ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
166
167 if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig(); 182 if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig();
168 if (m_EventManager != null) m_EventManager.ReadConfig(); 183 if (m_EventManager != null) m_EventManager.ReadConfig();
169 if (m_ScriptManager != null) m_ScriptManager.ReadConfig(); 184 if (m_ScriptManager != null) m_ScriptManager.ReadConfig();
@@ -189,13 +204,15 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
189 204
190 public bool PostObjectEvent(uint localID, EventParams p) 205 public bool PostObjectEvent(uint localID, EventParams p)
191 { 206 {
192 return m_EventQueueManager.AddToObjectQueue(localID, p.EventName, p.DetectParams, p.Params); 207 return m_EventQueueManager.AddToObjectQueue(localID, p.EventName,
208 p.DetectParams, p.Params);
193 } 209 }
194 210
195 public bool PostScriptEvent(UUID itemID, EventParams p) 211 public bool PostScriptEvent(UUID itemID, EventParams p)
196 { 212 {
197 uint localID = m_ScriptManager.GetLocalID(itemID); 213 uint localID = m_ScriptManager.GetLocalID(itemID);
198 return m_EventQueueManager.AddToScriptQueue(localID, itemID, p.EventName, p.DetectParams, p.Params); 214 return m_EventQueueManager.AddToScriptQueue(localID, itemID,
215 p.EventName, p.DetectParams, p.Params);
199 } 216 }
200 217
201 public DetectParams GetDetectParams(UUID itemID, int number) 218 public DetectParams GetDetectParams(UUID itemID, int number)
@@ -341,7 +358,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
341 id.Running = false; 358 id.Running = false;
342 } 359 }
343 360
344 public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) 361 public void OnGetScriptRunning(IClientAPI controllingClient,
362 UUID objectID, UUID itemID)
345 { 363 {
346 uint localID = m_ScriptManager.GetLocalID(itemID); 364 uint localID = m_ScriptManager.GetLocalID(itemID);
347 if (localID == 0) 365 if (localID == 0)