aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs')
-rw-r--r--OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs200
1 files changed, 200 insertions, 0 deletions
diff --git a/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs
new file mode 100644
index 0000000..9829c1d
--- /dev/null
+++ b/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs
@@ -0,0 +1,200 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Reflection;
5using System.Threading;
6using System.Runtime.Remoting;
7using System.IO;
8using OpenSim.Region.Environment.Scenes;
9using OpenSim.Region.Environment.Scenes.Scripting;
10using OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL;
11using OpenSim.Region.ScriptEngine.Common;
12using libsecondlife;
13
14namespace OpenSim.Grid.ScriptEngine.DotNetEngine
15{
16 public class AppDomainManager
17 {
18 private int maxScriptsPerAppDomain = 1;
19 /// <summary>
20 /// Internal list of all AppDomains
21 /// </summary>
22 private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
23 /// <summary>
24 /// Structure to keep track of data around AppDomain
25 /// </summary>
26 private class AppDomainStructure
27 {
28 /// <summary>
29 /// The AppDomain itself
30 /// </summary>
31 public AppDomain CurrentAppDomain;
32 /// <summary>
33 /// Number of scripts loaded into AppDomain
34 /// </summary>
35 public int ScriptsLoaded;
36 /// <summary>
37 /// Number of dead scripts
38 /// </summary>
39 public int ScriptsWaitingUnload;
40 }
41 /// <summary>
42 /// Current AppDomain
43 /// </summary>
44 private AppDomainStructure currentAD;
45 private object getLock = new object(); // Mutex
46 private object freeLock = new object(); // Mutex
47
48 //private ScriptEngine m_scriptEngine;
49 //public AppDomainManager(ScriptEngine scriptEngine)
50 public AppDomainManager()
51 {
52 //m_scriptEngine = scriptEngine;
53 }
54
55 /// <summary>
56 /// Find a free AppDomain, creating one if necessary
57 /// </summary>
58 /// <returns>Free AppDomain</returns>
59 private AppDomainStructure GetFreeAppDomain()
60 {
61 Console.WriteLine("Finding free AppDomain");
62 lock (getLock)
63 {
64 // Current full?
65 if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
66 {
67 // Add it to AppDomains list and empty current
68 appDomains.Add(currentAD);
69 currentAD = null;
70 }
71 // No current
72 if (currentAD == null)
73 {
74 // Create a new current AppDomain
75 currentAD = new AppDomainStructure();
76 currentAD.CurrentAppDomain = PrepareNewAppDomain();
77 }
78
79 Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
80 return currentAD;
81 } // lock
82 }
83
84 private int AppDomainNameCount;
85 /// <summary>
86 /// Create and prepare a new AppDomain for scripts
87 /// </summary>
88 /// <returns>The new AppDomain</returns>
89 private AppDomain PrepareNewAppDomain()
90 {
91 // Create and prepare a new AppDomain
92 AppDomainNameCount++;
93 // TODO: Currently security match current appdomain
94
95 // Construct and initialize settings for a second AppDomain.
96 AppDomainSetup ads = new AppDomainSetup();
97 ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
98 ads.DisallowBindingRedirects = false;
99 ads.DisallowCodeDownload = true;
100 ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;)
101 ads.ShadowCopyFiles = "true"; // Enabled shadowing
102 ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
103
104 AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
105 Console.WriteLine("Loading: " + AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString());
106 AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll"));
107
108 // Return the new AppDomain
109 return AD;
110
111 }
112
113 /// <summary>
114 /// Unload appdomains that are full and have only dead scripts
115 /// </summary>
116 private void UnloadAppDomains()
117 {
118 lock (freeLock)
119 {
120 // Go through all
121 foreach (AppDomainStructure ads in new System.Collections.ArrayList(appDomains))
122 {
123 // Don't process current AppDomain
124 if (ads.CurrentAppDomain != currentAD.CurrentAppDomain)
125 {
126 // Not current AppDomain
127 // Is number of unloaded bigger or equal to number of loaded?
128 if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload)
129 {
130 Console.WriteLine("Found empty AppDomain, unloading");
131 // Remove from internal list
132 appDomains.Remove(ads);
133#if DEBUG
134 long m = GC.GetTotalMemory(true);
135#endif
136 // Unload
137 AppDomain.Unload(ads.CurrentAppDomain);
138#if DEBUG
139 Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory");
140#endif
141 }
142 }
143 } // foreach
144 } // lock
145 }
146
147
148
149 public OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass LoadScript(string FileName)
150 {
151 // Find next available AppDomain to put it in
152 AppDomainStructure FreeAppDomain = GetFreeAppDomain();
153
154 Console.WriteLine("Loading into AppDomain: " + FileName);
155 LSL_BaseClass mbrt = (LSL_BaseClass)FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
156 //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
157 FreeAppDomain.ScriptsLoaded++;
158
159 return mbrt;
160 }
161
162
163 /// <summary>
164 /// Increase "dead script" counter for an AppDomain
165 /// </summary>
166 /// <param name="ad"></param>
167 //[Obsolete("Needs fixing, needs a real purpose in life!!!")]
168 public void StopScript(AppDomain ad)
169 {
170 lock (freeLock)
171 {
172 Console.WriteLine("Stopping script in AppDomain");
173 // Check if it is current AppDomain
174 if (currentAD.CurrentAppDomain == ad)
175 {
176 // Yes - increase
177 currentAD.ScriptsWaitingUnload++;
178 return;
179 }
180
181 // Lopp through all AppDomains
182 foreach (AppDomainStructure ads in new System.Collections.ArrayList(appDomains))
183 {
184 if (ads.CurrentAppDomain == ad)
185 {
186 // Found it
187 ads.ScriptsWaitingUnload++;
188 break;
189 }
190 } // foreach
191 } // lock
192
193 UnloadAppDomains(); // Outsite lock, has its own GetLock
194
195
196 }
197
198
199 }
200}