aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs510
1 files changed, 0 insertions, 510 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
deleted file mode 100644
index 987a0a0..0000000
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
+++ /dev/null
@@ -1,510 +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.Generic;
30using System.IO;
31using System.Reflection;
32using System.Runtime.Serialization.Formatters.Binary;
33using System.Threading;
34using OpenMetaverse;
35using OpenSim.Region.Environment.Scenes;
36using OpenSim.Region.ScriptEngine.Shared;
37
38namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
39{
40 /// <summary>
41 /// Loads scripts
42 /// Compiles them if necessary
43 /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
44 /// </summary>
45 ///
46
47 // This class is as close as you get to the script without being inside script class. It handles all the dirty work for other classes.
48 // * Keeps track of running scripts
49 // * Compiles script if necessary (through "Compiler")
50 // * Loads script (through "AppDomainManager" called from for example "EventQueueManager")
51 // * Executes functions inside script (called from for example "EventQueueManager" class)
52 // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager")
53 // * Dedicated load/unload thread, and queues loading/unloading.
54 // This so that scripts starting or stopping will not slow down other theads or whole system.
55 //
56 [Serializable]
57 public abstract class ScriptManager : iScriptEngineFunctionModule
58 {
59 #region Declares
60
61 private Thread scriptLoadUnloadThread;
62 private static Thread staticScriptLoadUnloadThread;
63 // private int scriptLoadUnloadThread_IdleSleepms;
64 private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
65 private static bool PrivateThread;
66 private int LoadUnloadMaxQueueSize;
67 private Object scriptLock = new Object();
68 private bool m_started = false;
69 private Dictionary<IScript, DetectParams[]> detparms = new Dictionary<IScript, DetectParams[]>();
70
71 // Load/Unload structure
72 private struct LUStruct
73 {
74 public uint localID;
75 public UUID itemID;
76 public string script;
77 public LUType Action;
78 public int startParam;
79 public bool postOnRez;
80 }
81
82 private enum LUType
83 {
84 Unknown = 0,
85 Load = 1,
86 Unload = 2
87 }
88
89 // Xantor 20080525: Keep a list of compiled scripts this session for reuse
90 public Dictionary<UUID, String> scriptList = new Dictionary<UUID, string>();
91
92 // Object<string, Script<string, script>>
93 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
94 // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
95 public Dictionary<uint, Dictionary<UUID, IScript>> Scripts =
96 new Dictionary<uint, Dictionary<UUID, IScript>>();
97
98
99 public Scene World
100 {
101 get { return m_scriptEngine.World; }
102 }
103
104 #endregion
105
106 public void ReadConfig()
107 {
108 // scriptLoadUnloadThread_IdleSleepms = m_scriptEngine.ScriptConfigSource.GetInt("ScriptLoadUnloadLoopms", 30);
109 // TODO: Requires sharing of all ScriptManagers to single thread
110 PrivateThread = true; // m_scriptEngine.ScriptConfigSource.GetBoolean("PrivateScriptLoadUnloadThread", false);
111 LoadUnloadMaxQueueSize = m_scriptEngine.ScriptConfigSource.GetInt("LoadUnloadMaxQueueSize", 100);
112 }
113
114 #region Object init/shutdown
115
116 public ScriptEngine m_scriptEngine;
117
118 public ScriptManager(ScriptEngine scriptEngine)
119 {
120 m_scriptEngine = scriptEngine;
121 }
122 public abstract void Initialize();
123 public void Setup()
124 {
125 ReadConfig();
126 Initialize();
127 }
128 public void Start()
129 {
130 m_started = true;
131
132
133 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
134
135 //
136 // CREATE THREAD
137 // Private or shared
138 //
139 if (PrivateThread)
140 {
141 // Assign one thread per region
142 //scriptLoadUnloadThread = StartScriptLoadUnloadThread();
143 }
144 else
145 {
146 // Shared thread - make sure one exist, then assign it to the private
147 if (staticScriptLoadUnloadThread == null)
148 {
149 //staticScriptLoadUnloadThread = StartScriptLoadUnloadThread();
150 }
151 scriptLoadUnloadThread = staticScriptLoadUnloadThread;
152 }
153 }
154
155// TODO: unused
156// private static int privateThreadCount = 0;
157// private Thread StartScriptLoadUnloadThread()
158// {
159// Thread t = new Thread(ScriptLoadUnloadThreadLoop);
160// string name = "ScriptLoadUnloadThread:";
161// if (PrivateThread)
162// {
163// name += "Private:" + privateThreadCount;
164// privateThreadCount++;
165// }
166// else
167// {
168// name += "Shared";
169// }
170// t.Name = name;
171// t.IsBackground = true;
172// t.Priority = ThreadPriority.Normal;
173// t.Start();
174// OpenSim.Framework.ThreadTracker.Add(t);
175// return t;
176// }
177
178 ~ScriptManager()
179 {
180 // Abort load/unload thread
181 try
182 {
183 //PleaseShutdown = true;
184 //Thread.Sleep(100);
185 if (scriptLoadUnloadThread != null && scriptLoadUnloadThread.IsAlive == true)
186 {
187 scriptLoadUnloadThread.Abort();
188 //scriptLoadUnloadThread.Join();
189 }
190 }
191 catch
192 {
193 }
194 }
195
196 #endregion
197
198 #region Load / Unload scripts (Thread loop)
199
200// TODO: unused
201// private void ScriptLoadUnloadThreadLoop()
202// {
203// try
204// {
205// while (true)
206// {
207// if (LUQueue.Count == 0)
208// Thread.Sleep(scriptLoadUnloadThread_IdleSleepms);
209// //if (PleaseShutdown)
210// // return;
211// DoScriptLoadUnload();
212// }
213// }
214// catch (ThreadAbortException tae)
215// {
216// string a = tae.ToString();
217// a = String.Empty;
218// // Expected
219// }
220// }
221
222 public void DoScriptLoadUnload()
223 {
224 if (!m_started)
225 return;
226
227 lock (LUQueue)
228 {
229 if (LUQueue.Count > 0)
230 {
231m_scriptEngine.Log.InfoFormat("[{0}]: Loading script", m_scriptEngine.ScriptEngineName);
232 LUStruct item = LUQueue.Dequeue();
233
234 if (item.Action == LUType.Unload)
235 {
236 _StopScript(item.localID, item.itemID);
237 RemoveScript(item.localID, item.itemID);
238 }
239 else if (item.Action == LUType.Load)
240 {
241 _StartScript(item.localID, item.itemID, item.script, item.startParam, item.postOnRez);
242 }
243 }
244 }
245 }
246
247 #endregion
248
249 #region Helper functions
250
251 private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
252 {
253 //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name);
254 return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null;
255 }
256
257 #endregion
258
259
260
261 #region Start/Stop/Reset script
262
263 // private readonly Object startStopLock = new Object();
264
265 /// <summary>
266 /// Fetches, loads and hooks up a script to an objects events
267 /// </summary>
268 /// <param name="itemID"></param>
269 /// <param name="localID"></param>
270 public void StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez)
271 {
272 lock (LUQueue)
273 {
274 if ((LUQueue.Count >= LoadUnloadMaxQueueSize) && m_started)
275 {
276 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: ERROR: Load/unload queue item count is at " + LUQueue.Count + ". Config variable \"LoadUnloadMaxQueueSize\" is set to " + LoadUnloadMaxQueueSize + ", so ignoring new script.");
277 return;
278 }
279
280 LUStruct ls = new LUStruct();
281 ls.localID = localID;
282 ls.itemID = itemID;
283 ls.script = Script;
284 ls.Action = LUType.Load;
285 ls.startParam = startParam;
286 ls.postOnRez = postOnRez;
287 LUQueue.Enqueue(ls);
288m_scriptEngine.Log.InfoFormat("[{0}]: Queued script for load", m_scriptEngine.ScriptEngineName);
289 }
290 }
291
292 /// <summary>
293 /// Disables and unloads a script
294 /// </summary>
295 /// <param name="localID"></param>
296 /// <param name="itemID"></param>
297 public void StopScript(uint localID, UUID itemID)
298 {
299 LUStruct ls = new LUStruct();
300 ls.localID = localID;
301 ls.itemID = itemID;
302 ls.Action = LUType.Unload;
303 ls.startParam = 0;
304 ls.postOnRez = false;
305 lock (LUQueue)
306 {
307 LUQueue.Enqueue(ls);
308 }
309 }
310
311 // Create a new instance of the compiler (reuse)
312 //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler();
313
314 public abstract void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez);
315 public abstract void _StopScript(uint localID, UUID itemID);
316
317
318 #endregion
319
320 #region Perform event execution in script
321
322 /// <summary>
323 /// Execute a LL-event-function in Script
324 /// </summary>
325 /// <param name="localID">Object the script is located in</param>
326 /// <param name="itemID">Script ID</param>
327 /// <param name="FunctionName">Name of function</param>
328 /// <param name="args">Arguments to pass to function</param>
329 internal void ExecuteEvent(uint localID, UUID itemID, string FunctionName, DetectParams[] qParams, object[] args)
330 {
331 //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
332 ///#if DEBUG
333 /// Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName);
334 ///#endif
335 // Execute a function in the script
336 //m_scriptEngine.Log.Info("[" + ScriptEngineName + "]: Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
337 //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
338 IScript Script = GetScript(localID, itemID);
339 if (Script == null)
340 {
341 return;
342 }
343 //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
344 ///#if DEBUG
345 /// Console.WriteLine("ScriptEngine: Executing event: " + FunctionName);
346 ///#endif
347 // Must be done in correct AppDomain, so leaving it up to the script itself
348 detparms[Script] = qParams;
349 Script.Exec.ExecuteEvent(FunctionName, args);
350 detparms.Remove(Script);
351 }
352
353 public uint GetLocalID(UUID itemID)
354 {
355 foreach (KeyValuePair<uint, Dictionary<UUID, IScript> > k in Scripts)
356 {
357 if (k.Value.ContainsKey(itemID))
358 return k.Key;
359 }
360 return 0;
361 }
362
363 public int GetStateEventFlags(uint localID, UUID itemID)
364 {
365 // Console.WriteLine("GetStateEventFlags for <" + localID + "," + itemID + ">");
366 try
367 {
368 IScript Script = GetScript(localID, itemID);
369 if (Script == null)
370 {
371 return 0;
372 }
373 ExecutorBase.scriptEvents evflags = Script.Exec.GetStateEventFlags();
374 return (int)evflags;
375 }
376 catch (Exception)
377 {
378 }
379
380 return 0;
381 }
382
383
384 #endregion
385
386 #region Internal functions to keep track of script
387
388 public List<UUID> GetScriptKeys(uint localID)
389 {
390 if (Scripts.ContainsKey(localID) == false)
391 return new List<UUID>();
392
393 Dictionary<UUID, IScript> Obj;
394 Scripts.TryGetValue(localID, out Obj);
395
396 return new List<UUID>(Obj.Keys);
397 }
398
399 public IScript GetScript(uint localID, UUID itemID)
400 {
401 lock (scriptLock)
402 {
403 IScript Script = null;
404
405 if (Scripts.ContainsKey(localID) == false)
406 return null;
407
408 Dictionary<UUID, IScript> Obj;
409 Scripts.TryGetValue(localID, out Obj);
410 if (Obj.ContainsKey(itemID) == false)
411 return null;
412
413 // Get script
414 Obj.TryGetValue(itemID, out Script);
415 return Script;
416 }
417 }
418
419 public void SetScript(uint localID, UUID itemID, IScript Script)
420 {
421 lock (scriptLock)
422 {
423 // Create object if it doesn't exist
424 if (Scripts.ContainsKey(localID) == false)
425 {
426 Scripts.Add(localID, new Dictionary<UUID, IScript>());
427 }
428
429 // Delete script if it exists
430 Dictionary<UUID, IScript> Obj;
431 Scripts.TryGetValue(localID, out Obj);
432 if (Obj.ContainsKey(itemID) == true)
433 Obj.Remove(itemID);
434
435 // Add to object
436 Obj.Add(itemID, Script);
437 }
438 }
439
440 public void RemoveScript(uint localID, UUID itemID)
441 {
442 if (localID == 0)
443 localID = GetLocalID(itemID);
444
445 // Don't have that object?
446 if (Scripts.ContainsKey(localID) == false)
447 return;
448
449 // Delete script if it exists
450 Dictionary<UUID, IScript> Obj;
451 Scripts.TryGetValue(localID, out Obj);
452 if (Obj.ContainsKey(itemID) == true)
453 Obj.Remove(itemID);
454 }
455
456 #endregion
457
458
459 public void ResetScript(uint localID, UUID itemID)
460 {
461 IScript s = GetScript(localID, itemID);
462 string script = s.Source;
463 StopScript(localID, itemID);
464 SceneObjectPart part = World.GetSceneObjectPart(localID);
465 part.GetInventoryItem(itemID).PermsMask = 0;
466 part.GetInventoryItem(itemID).PermsGranter = UUID.Zero;
467 StartScript(localID, itemID, script, s.StartParam, false);
468 }
469
470
471 #region Script serialization/deserialization
472
473 public void GetSerializedScript(uint localID, UUID itemID)
474 {
475 // Serialize the script and return it
476 // Should not be a problem
477 FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID);
478 BinaryFormatter b = new BinaryFormatter();
479 b.Serialize(fs, GetScript(localID, itemID));
480 fs.Close();
481 }
482
483 public void PutSerializedScript(uint localID, UUID itemID)
484 {
485 // Deserialize the script and inject it into an AppDomain
486
487 // How to inject into an AppDomain?
488 }
489
490 #endregion
491
492 ///// <summary>
493 ///// If set to true then threads and stuff should try to make a graceful exit
494 ///// </summary>
495 //public bool PleaseShutdown
496 //{
497 // get { return _PleaseShutdown; }
498 // set { _PleaseShutdown = value; }
499 //}
500 //private bool _PleaseShutdown = false;
501
502 public DetectParams[] GetDetectParams(IScript script)
503 {
504 if (detparms.ContainsKey(script))
505 return detparms[script];
506
507 return null;
508 }
509 }
510}