aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine/XEngine.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs123
1 files changed, 64 insertions, 59 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 7b19ce3..a60c0ba 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -50,6 +50,8 @@ using OpenSim.Region.ScriptEngine.Shared.CodeTools;
50using OpenSim.Region.ScriptEngine.Shared.Instance; 50using OpenSim.Region.ScriptEngine.Shared.Instance;
51using OpenSim.Region.ScriptEngine.Interfaces; 51using OpenSim.Region.ScriptEngine.Interfaces;
52 52
53using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>;
54
53namespace OpenSim.Region.ScriptEngine.XEngine 55namespace OpenSim.Region.ScriptEngine.XEngine
54{ 56{
55 public class XEngine : INonSharedRegionModule, IScriptModule, IScriptEngine 57 public class XEngine : INonSharedRegionModule, IScriptModule, IScriptEngine
@@ -73,9 +75,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
73 private bool m_InitialStartup = true; 75 private bool m_InitialStartup = true;
74 private int m_ScriptFailCount; // Number of script fails since compile queue was last empty 76 private int m_ScriptFailCount; // Number of script fails since compile queue was last empty
75 private string m_ScriptErrorMessage; 77 private string m_ScriptErrorMessage;
78 private Dictionary<string, string> m_uniqueScripts = new Dictionary<string, string>();
79 private bool m_AppDomainLoading;
76 80
77// disable warning: need to keep a reference to XEngine.EventManager 81 // disable warning: need to keep a reference to XEngine.EventManager
78// alive to avoid it being garbage collected 82 // alive to avoid it being garbage collected
79#pragma warning disable 414 83#pragma warning disable 414
80 private EventManager m_EventManager; 84 private EventManager m_EventManager;
81#pragma warning restore 414 85#pragma warning restore 414
@@ -114,7 +118,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
114 private Dictionary<UUID, List<UUID> > m_DomainScripts = 118 private Dictionary<UUID, List<UUID> > m_DomainScripts =
115 new Dictionary<UUID, List<UUID> >(); 119 new Dictionary<UUID, List<UUID> >();
116 120
117 private Queue m_CompileQueue = new Queue(100); 121 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
118 IWorkItemResult m_CurrentCompile = null; 122 IWorkItemResult m_CurrentCompile = null;
119 123
120 public string ScriptEngineName 124 public string ScriptEngineName
@@ -201,6 +205,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
201 m_MaxScriptQueue = m_ScriptConfig.GetInt("MaxScriptEventQueue",300); 205 m_MaxScriptQueue = m_ScriptConfig.GetInt("MaxScriptEventQueue",300);
202 m_StackSize = m_ScriptConfig.GetInt("ThreadStackSize", 262144); 206 m_StackSize = m_ScriptConfig.GetInt("ThreadStackSize", 262144);
203 m_SleepTime = m_ScriptConfig.GetInt("MaintenanceInterval", 10) * 1000; 207 m_SleepTime = m_ScriptConfig.GetInt("MaintenanceInterval", 10) * 1000;
208 m_AppDomainLoading = m_ScriptConfig.GetBoolean("AppDomainLoading", true);
204 209
205 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); 210 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
206 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); 211 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
@@ -470,6 +475,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
470 if (engine != ScriptEngineName) 475 if (engine != ScriptEngineName)
471 return; 476 return;
472 477
478 // If we've seen this exact script text before, use that reference instead
479 if (m_uniqueScripts.ContainsKey(script))
480 script = m_uniqueScripts[script];
481 else
482 m_uniqueScripts[script] = script;
483
473 Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource}; 484 Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource};
474 485
475 if (stateSource == (int)StateSource.ScriptedRez) 486 if (stateSource == (int)StateSource.ScriptedRez)
@@ -478,15 +489,19 @@ namespace OpenSim.Region.ScriptEngine.XEngine
478 } 489 }
479 else 490 else
480 { 491 {
481 lock (m_CompileQueue) 492 m_CompileQueue.Enqueue(parms);
482 {
483 m_CompileQueue.Enqueue(parms);
484 493
485 if (m_CurrentCompile == null) 494 if (m_CurrentCompile == null)
495 {
496 // NOTE: Although we use a lockless queue, the lock here
497 // is required. It ensures that there are never two
498 // compile threads running, which, due to a race
499 // conndition, might otherwise happen
500 //
501 lock (m_CompileQueue)
486 { 502 {
487 m_CurrentCompile = m_ThreadPool.QueueWorkItem( 503 if (m_CurrentCompile == null)
488 new WorkItemCallback(this.DoOnRezScriptQueue), 504 m_CurrentCompile = m_ThreadPool.QueueWorkItem(DoOnRezScriptQueue, null);
489 new Object[0]);
490 } 505 }
491 } 506 }
492 } 507 }
@@ -498,50 +513,38 @@ namespace OpenSim.Region.ScriptEngine.XEngine
498 { 513 {
499 m_InitialStartup = false; 514 m_InitialStartup = false;
500 System.Threading.Thread.Sleep(15000); 515 System.Threading.Thread.Sleep(15000);
501 lock (m_CompileQueue)
502 {
503 if (m_CompileQueue.Count==0)
504 // No scripts on region, so won't get triggered later
505 // by the queue becoming empty so we trigger it here
506 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(0, String.Empty);
507 }
508 }
509 516
510 Object o; 517 if (m_CompileQueue.Count == 0)
511 lock (m_CompileQueue)
512 {
513 o = m_CompileQueue.Dequeue();
514 if (o == null)
515 { 518 {
516 m_CurrentCompile = null; 519 // No scripts on region, so won't get triggered later
517 return null; 520 // by the queue becoming empty so we trigger it here
521 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(0, String.Empty);
518 } 522 }
519 } 523 }
520 524
521 DoOnRezScript(o); 525 object[] o;
526 while (m_CompileQueue.Dequeue(out o))
527 DoOnRezScript(o);
522 528
529 // NOTE: Despite having a lockless queue, this lock is required
530 // to make sure there is never no compile thread while there
531 // are still scripts to compile. This could otherwise happen
532 // due to a race condition
533 //
523 lock (m_CompileQueue) 534 lock (m_CompileQueue)
524 { 535 {
525 if (m_CompileQueue.Count > 0) 536 m_CurrentCompile = null;
526 {
527 m_CurrentCompile = m_ThreadPool.QueueWorkItem(
528 new WorkItemCallback(this.DoOnRezScriptQueue),
529 new Object[0]);
530 }
531 else
532 {
533 m_CurrentCompile = null;
534 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount,
535 m_ScriptErrorMessage);
536 m_ScriptFailCount = 0;
537 }
538 } 537 }
538 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount,
539 m_ScriptErrorMessage);
540 m_ScriptFailCount = 0;
541
539 return null; 542 return null;
540 } 543 }
541 544
542 private bool DoOnRezScript(object parm) 545 private bool DoOnRezScript(object[] parms)
543 { 546 {
544 Object[] p = (Object[])parm; 547 Object[] p = parms;
545 uint localID = (uint)p[0]; 548 uint localID = (uint)p[0];
546 UUID itemID = (UUID)p[1]; 549 UUID itemID = (UUID)p[1];
547 string script =(string)p[2]; 550 string script =(string)p[2];
@@ -590,14 +593,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
590 { 593 {
591 lock (m_AddingAssemblies) 594 lock (m_AddingAssemblies)
592 { 595 {
593 assembly = (string)m_Compiler.PerformScriptCompile(script, 596 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap);
594 assetID.ToString(), item.OwnerID);
595 if (!m_AddingAssemblies.ContainsKey(assembly)) { 597 if (!m_AddingAssemblies.ContainsKey(assembly)) {
596 m_AddingAssemblies[assembly] = 1; 598 m_AddingAssemblies[assembly] = 1;
597 } else { 599 } else {
598 m_AddingAssemblies[assembly]++; 600 m_AddingAssemblies[assembly]++;
599 } 601 }
600 linemap = m_Compiler.LineMap();
601 } 602 }
602 603
603 string[] warnings = m_Compiler.GetWarnings(); 604 string[] warnings = m_Compiler.GetWarnings();
@@ -696,19 +697,22 @@ namespace OpenSim.Region.ScriptEngine.XEngine
696 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 697 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
697 Evidence evidence = new Evidence(baseEvidence); 698 Evidence evidence = new Evidence(baseEvidence);
698 699
699 AppDomain sandbox = 700 AppDomain sandbox;
700 AppDomain.CreateDomain( 701 if (m_AppDomainLoading)
701 m_Scene.RegionInfo.RegionID.ToString(), 702 sandbox = AppDomain.CreateDomain(
702 evidence, appSetup); 703 m_Scene.RegionInfo.RegionID.ToString(),
703/* 704 evidence, appSetup);
704 PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 705 else
705 AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 706 sandbox = AppDomain.CurrentDomain;
706 PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 707
707 PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 708 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
708 CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 709 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
709 sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 710 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
710 sandbox.SetAppDomainPolicy(sandboxPolicy); 711 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
711*/ 712 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
713 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
714 //sandbox.SetAppDomainPolicy(sandboxPolicy);
715
712 m_AppDomains[appDomain] = sandbox; 716 m_AppDomains[appDomain] = sandbox;
713 717
714 m_AppDomains[appDomain].AssemblyResolve += 718 m_AppDomains[appDomain].AssemblyResolve +=
@@ -905,9 +909,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
905 AppDomain domain = m_AppDomains[id]; 909 AppDomain domain = m_AppDomains[id];
906 m_AppDomains.Remove(id); 910 m_AppDomains.Remove(id);
907 911
908 AppDomain.Unload(domain); 912 if (domain != AppDomain.CurrentDomain)
913 AppDomain.Unload(domain);
909 domain = null; 914 domain = null;
910// m_log.DebugFormat("[XEngine] Unloaded app domain {0}", id.ToString()); 915 // m_log.DebugFormat("[XEngine] Unloaded app domain {0}", id.ToString());
911 } 916 }
912 } 917 }
913 918