aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
diff options
context:
space:
mode:
authorMelanie Thielker2008-09-26 13:16:11 +0000
committerMelanie Thielker2008-09-26 13:16:11 +0000
commit824283ca3c2ab54868ed61fdb0a329221d69e5fa (patch)
tree9013892fa2afa579bffe8bdcd6a46e2242ed085c /OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
parent* Wind updates. Still random.. but in 4 directions instead of two! (diff)
downloadopensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.zip
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.gz
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.bz2
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.xz
Remove all the subclassing complexity and script server interfaces from
DNE and move all of DNE into the DotNetEngine directory. Remove references that would cause the script runtime to load the entire engine + scene into each script appdomain. This might help DNE memory consumption.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs253
1 files changed, 0 insertions, 253 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
deleted file mode 100644
index 262d75f..0000000
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
+++ /dev/null
@@ -1,253 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32
33namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
34{
35 public class AppDomainManager : iScriptEngineFunctionModule
36 {
37 //
38 // This class does AppDomain handling and loading/unloading of scripts in it.
39 // It is instanced in "ScriptEngine" and controlled from "ScriptManager"
40 //
41 // 1. Create a new AppDomain if old one is full (or doesn't exist)
42 // 2. Load scripts into AppDomain
43 // 3. Unload scripts from AppDomain (stopping them and marking them as inactive)
44 // 4. Unload AppDomain completely when all scripts in it has stopped
45 //
46
47 private int maxScriptsPerAppDomain = 1;
48
49 /// <summary>
50 /// Internal list of all AppDomains
51 /// </summary>
52 private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
53
54 /// <summary>
55 /// Structure to keep track of data around AppDomain
56 /// </summary>
57 private class AppDomainStructure
58 {
59 /// <summary>
60 /// The AppDomain itself
61 /// </summary>
62 public AppDomain CurrentAppDomain;
63
64 /// <summary>
65 /// Number of scripts loaded into AppDomain
66 /// </summary>
67 public int ScriptsLoaded;
68
69 /// <summary>
70 /// Number of dead scripts
71 /// </summary>
72 public int ScriptsWaitingUnload;
73 }
74
75 /// <summary>
76 /// Current AppDomain
77 /// </summary>
78 private AppDomainStructure currentAD;
79
80 private object getLock = new object(); // Mutex
81 private object freeLock = new object(); // Mutex
82
83 private ScriptEngine m_scriptEngine;
84 //public AppDomainManager(ScriptEngine scriptEngine)
85 public AppDomainManager(ScriptEngine scriptEngine)
86 {
87 m_scriptEngine = scriptEngine;
88 ReadConfig();
89 }
90
91 public void ReadConfig()
92 {
93 maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1);
94 }
95
96 /// <summary>
97 /// Find a free AppDomain, creating one if necessary
98 /// </summary>
99 /// <returns>Free AppDomain</returns>
100 private AppDomainStructure GetFreeAppDomain()
101 {
102 // Console.WriteLine("Finding free AppDomain");
103 lock (getLock)
104 {
105 // Current full?
106 if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
107 {
108 // Add it to AppDomains list and empty current
109 appDomains.Add(currentAD);
110 currentAD = null;
111 }
112 // No current
113 if (currentAD == null)
114 {
115 // Create a new current AppDomain
116 currentAD = new AppDomainStructure();
117 currentAD.CurrentAppDomain = PrepareNewAppDomain();
118 }
119
120 // Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
121 return currentAD;
122 }
123 }
124
125 private int AppDomainNameCount;
126
127 /// <summary>
128 /// Create and prepare a new AppDomain for scripts
129 /// </summary>
130 /// <returns>The new AppDomain</returns>
131 private AppDomain PrepareNewAppDomain()
132 {
133 // Create and prepare a new AppDomain
134 AppDomainNameCount++;
135 // TODO: Currently security match current appdomain
136
137 // Construct and initialize settings for a second AppDomain.
138 AppDomainSetup ads = new AppDomainSetup();
139 ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
140 ads.DisallowBindingRedirects = true;
141 ads.DisallowCodeDownload = true;
142 ads.LoaderOptimization = LoaderOptimization.MultiDomainHost;
143 ads.ShadowCopyFiles = "false"; // Disable shadowing
144 ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
145
146
147 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
148 m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain Loading: " +
149 AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString());
150 AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll"));
151
152 // Return the new AppDomain
153 return AD;
154 }
155
156 /// <summary>
157 /// Unload appdomains that are full and have only dead scripts
158 /// </summary>
159 private void UnloadAppDomains()
160 {
161 lock (freeLock)
162 {
163 // Go through all
164 foreach (AppDomainStructure ads in new ArrayList(appDomains))
165 {
166 // Don't process current AppDomain
167 if (ads.CurrentAppDomain != currentAD.CurrentAppDomain)
168 {
169 // Not current AppDomain
170 // Is number of unloaded bigger or equal to number of loaded?
171 if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload)
172 {
173 // Remove from internal list
174 appDomains.Remove(ads);
175//#if DEBUG
176 //Console.WriteLine("Found empty AppDomain, unloading");
177 //long m = GC.GetTotalMemory(true); // This force a garbage collect that freezes some windows plateforms
178//#endif
179 // Unload
180 AppDomain.Unload(ads.CurrentAppDomain);
181//#if DEBUG
182 //m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory");
183//#endif
184 }
185 }
186 }
187 }
188 }
189
190 public IScript LoadScript(string FileName)
191 {
192 // Find next available AppDomain to put it in
193 AppDomainStructure FreeAppDomain = GetFreeAppDomain();
194
195#if DEBUG
196 m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Loading into AppDomain: " + FileName);
197#endif
198 IScript mbrt =
199 (IScript)
200 FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
201 //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
202 FreeAppDomain.ScriptsLoaded++;
203
204 return mbrt;
205 }
206
207
208 /// <summary>
209 /// Increase "dead script" counter for an AppDomain
210 /// </summary>
211 /// <param name="ad"></param>
212 //[Obsolete("Needs fixing, needs a real purpose in life!!!")]
213 public void StopScript(AppDomain ad)
214 {
215 lock (freeLock)
216 {
217#if DEBUG
218 m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Stopping script in AppDomain");
219#endif
220 // Check if it is current AppDomain
221 if (currentAD.CurrentAppDomain == ad)
222 {
223 // Yes - increase
224 currentAD.ScriptsWaitingUnload++;
225 return;
226 }
227
228 // Lopp through all AppDomains
229 foreach (AppDomainStructure ads in new ArrayList(appDomains))
230 {
231 if (ads.CurrentAppDomain == ad)
232 {
233 // Found it
234 ads.ScriptsWaitingUnload++;
235 break;
236 }
237 }
238 }
239
240 UnloadAppDomains(); // Outsite lock, has its own GetLock
241 }
242
243 /// <summary>
244 /// If set to true then threads and stuff should try to make a graceful exit
245 /// </summary>
246 public bool PleaseShutdown
247 {
248 get { return _PleaseShutdown; }
249 set { _PleaseShutdown = value; }
250 }
251 private bool _PleaseShutdown = false;
252 }
253}