aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/ScriptEngine/XEngine/XEngine.cs529
1 files changed, 400 insertions, 129 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 1831c39..466c190 100644..100755
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -43,6 +43,7 @@ using OpenMetaverse.StructuredData;
43using log4net; 43using log4net;
44using Nini.Config; 44using Nini.Config;
45using Amib.Threading; 45using Amib.Threading;
46using Mono.Addins;
46using OpenSim.Framework; 47using OpenSim.Framework;
47using OpenSim.Framework.Console; 48using OpenSim.Framework.Console;
48using OpenSim.Region.Framework.Scenes; 49using OpenSim.Region.Framework.Scenes;
@@ -61,6 +62,7 @@ using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>;
61 62
62namespace OpenSim.Region.ScriptEngine.XEngine 63namespace OpenSim.Region.ScriptEngine.XEngine
63{ 64{
65 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEngine")]
64 public class XEngine : INonSharedRegionModule, IScriptModule, IScriptEngine 66 public class XEngine : INonSharedRegionModule, IScriptModule, IScriptEngine
65 { 67 {
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -71,7 +73,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
71 /// <remarks> 73 /// <remarks>
72 /// If DebugLevel >= 1, then we log every time that a script is started. 74 /// If DebugLevel >= 1, then we log every time that a script is started.
73 /// </remarks> 75 /// </remarks>
74// public int DebugLevel { get; set; } 76 public int DebugLevel { get; set; }
77
78 /// <summary>
79 /// A parameter to allow us to notify the log if at least one script has a compilation that is not compatible
80 /// with ScriptStopStrategy.
81 /// </summary>
82 public bool HaveNotifiedLogOfScriptStopMistmatch { get; private set; }
75 83
76 private SmartThreadPool m_ThreadPool; 84 private SmartThreadPool m_ThreadPool;
77 private int m_MaxScriptQueue; 85 private int m_MaxScriptQueue;
@@ -87,6 +95,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
87 /// </summary> 95 /// </summary>
88 private int m_StartDelay; 96 private int m_StartDelay;
89 97
98 /// <summary>
99 /// Are we stopping scripts co-operatively by inserting checks in them at C# compile time (true) or aborting
100 /// their threads (false)?
101 /// </summary>
102 private bool m_coopTermination;
103
90 private int m_IdleTimeout; 104 private int m_IdleTimeout;
91 private int m_StackSize; 105 private int m_StackSize;
92 private int m_SleepTime; 106 private int m_SleepTime;
@@ -96,7 +110,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
96 private bool m_InitialStartup = true; 110 private bool m_InitialStartup = true;
97 private int m_ScriptFailCount; // Number of script fails since compile queue was last empty 111 private int m_ScriptFailCount; // Number of script fails since compile queue was last empty
98 private string m_ScriptErrorMessage; 112 private string m_ScriptErrorMessage;
99 private Dictionary<string, string> m_uniqueScripts = new Dictionary<string, string>();
100 private bool m_AppDomainLoading; 113 private bool m_AppDomainLoading;
101 private Dictionary<UUID,ArrayList> m_ScriptErrors = 114 private Dictionary<UUID,ArrayList> m_ScriptErrors =
102 new Dictionary<UUID,ArrayList>(); 115 new Dictionary<UUID,ArrayList>();
@@ -308,12 +321,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
308 m_ScriptConfig = configSource.Configs["XEngine"]; 321 m_ScriptConfig = configSource.Configs["XEngine"];
309 m_ConfigSource = configSource; 322 m_ConfigSource = configSource;
310 323
311 string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "abort"); 324 string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "co-op");
312 325
313 m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy); 326 m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy);
314 327
315 if (rawScriptStopStrategy == "co-op") 328 if (rawScriptStopStrategy == "co-op")
316 { 329 {
330 m_coopTermination = true;
317 ScriptClassName = "XEngineScript"; 331 ScriptClassName = "XEngineScript";
318 ScriptBaseClassName = typeof(XEngineScriptBase).FullName; 332 ScriptBaseClassName = typeof(XEngineScriptBase).FullName;
319 ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters(); 333 ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters();
@@ -457,19 +471,19 @@ namespace OpenSim.Region.ScriptEngine.XEngine
457 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); 471 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
458 472
459 MainConsole.Instance.Commands.AddCommand( 473 MainConsole.Instance.Commands.AddCommand(
460 "Scripts", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script", 474 "Debug", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a particular script.",
461 "Activates or deactivates extra debug logging for the given script.\n" 475 "Activates or deactivates extra debug logging for the given script.\n"
462 + "Level == 0, deactivate extra debug logging.\n" 476 + "Level == 0, deactivate extra debug logging.\n"
463 + "Level >= 1, log state changes.\n" 477 + "Level >= 1, log state changes.\n"
464 + "Level >= 2, log event invocations.\n", 478 + "Level >= 2, log event invocations.\n",
465 HandleDebugScriptLogCommand); 479 HandleDebugScriptLogCommand);
466 480
467// MainConsole.Instance.Commands.AddCommand( 481 MainConsole.Instance.Commands.AddCommand(
468// "Debug", false, "debug xengine", "debug xengine [<level>]", 482 "Debug", false, "debug xengine log", "debug xengine log [<level>]",
469// "Turn on detailed xengine debugging.", 483 "Turn on detailed xengine debugging.",
470// "If level <= 0, then no extra logging is done.\n" 484 "If level <= 0, then no extra logging is done.\n"
471// + "If level >= 1, then we log every time that a script is started.", 485 + "If level >= 1, then we log every time that a script is started.",
472// HandleDebugLevelCommand); 486 HandleDebugLevelCommand);
473 } 487 }
474 488
475 private void HandleDebugScriptLogCommand(string module, string[] args) 489 private void HandleDebugScriptLogCommand(string module, string[] args)
@@ -512,26 +526,26 @@ namespace OpenSim.Region.ScriptEngine.XEngine
512 /// </summary> 526 /// </summary>
513 /// <param name="module"></param> 527 /// <param name="module"></param>
514 /// <param name="args"></param> 528 /// <param name="args"></param>
515// private void HandleDebugLevelCommand(string module, string[] args) 529 private void HandleDebugLevelCommand(string module, string[] args)
516// { 530 {
517// if (args.Length == 3) 531 if (args.Length >= 4)
518// { 532 {
519// int newDebug; 533 int newDebug;
520// if (int.TryParse(args[2], out newDebug)) 534 if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, args[3], out newDebug))
521// { 535 {
522// DebugLevel = newDebug; 536 DebugLevel = newDebug;
523// MainConsole.Instance.OutputFormat("Debug level set to {0}", newDebug); 537 MainConsole.Instance.OutputFormat("Debug level set to {0} in XEngine for region {1}", newDebug, m_Scene.Name);
524// } 538 }
525// } 539 }
526// else if (args.Length == 2) 540 else if (args.Length == 3)
527// { 541 {
528// MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel); 542 MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel);
529// } 543 }
530// else 544 else
531// { 545 {
532// MainConsole.Instance.Output("Usage: debug xengine 0..1"); 546 MainConsole.Instance.Output("Usage: debug xengine log <level>");
533// } 547 }
534// } 548 }
535 549
536 /// <summary> 550 /// <summary>
537 /// Parse the raw item id into a script instance from the command params if it's present. 551 /// Parse the raw item id into a script instance from the command params if it's present.
@@ -631,7 +645,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
631 } 645 }
632 646
633 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded); 647 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
634 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
635 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 648 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
636 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 649 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
637 sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads); 650 sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads);
@@ -754,6 +767,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
754 { 767 {
755 if (instance.Running) 768 if (instance.Running)
756 { 769 {
770 instance.StayStopped = true; // the script was stopped explicitly
771
757 instance.Stop(0); 772 instance.Stop(0);
758 773
759 SceneObjectPart sop = m_Scene.GetSceneObjectPart(instance.ObjectID); 774 SceneObjectPart sop = m_Scene.GetSceneObjectPart(instance.ObjectID);
@@ -778,11 +793,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
778 // 793 //
779 if (m_Assemblies.ContainsKey(instance.AssetID)) 794 if (m_Assemblies.ContainsKey(instance.AssetID))
780 { 795 {
796<<<<<<< HEAD
797 // Force a final state save
798 //
799 try
800 {
801 if (instance.StatePersistedHere)
802 instance.SaveState();
803=======
781 string assembly = m_Assemblies[instance.AssetID]; 804 string assembly = m_Assemblies[instance.AssetID];
782 805
783 try 806 try
784 { 807 {
785 instance.SaveState(assembly); 808 instance.SaveState(assembly);
809>>>>>>> avn/ubitvar
786 } 810 }
787 catch (Exception e) 811 catch (Exception e)
788 { 812 {
@@ -794,10 +818,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
794 } 818 }
795 } 819 }
796 820
821<<<<<<< HEAD
822 // Clear the event queue and abort the instance thread
823 //
824 instance.Stop(0, true);
825=======
797 // Clear the event queue and abort the instance thread 826 // Clear the event queue and abort the instance thread
798 // 827 //
799 instance.ClearQueue(); 828 instance.ClearQueue();
800 instance.Stop(0); 829 instance.Stop(0);
830>>>>>>> avn/ubitvar
801 831
802 // Release events, timer, etc 832 // Release events, timer, etc
803 // 833 //
@@ -898,6 +928,25 @@ namespace OpenSim.Region.ScriptEngine.XEngine
898 928
899 List<IScriptInstance> instances = new List<IScriptInstance>(); 929 List<IScriptInstance> instances = new List<IScriptInstance>();
900 930
931<<<<<<< HEAD
932 lock (m_Scripts)
933 {
934 foreach (IScriptInstance instance in m_Scripts.Values)
935 {
936 if (instance.StatePersistedHere)
937 {
938// m_log.DebugFormat(
939// "[XEngine]: Adding script {0}.{1}, item UUID {2}, prim UUID {3} in {4} for state persistence",
940// instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name);
941
942 instances.Add(instance);
943 }
944 }
945 }
946
947 foreach (IScriptInstance i in instances)
948 {
949=======
901 lockScriptsForRead(true); 950 lockScriptsForRead(true);
902 foreach (IScriptInstance instance in m_Scripts.Values) 951 foreach (IScriptInstance instance in m_Scripts.Values)
903 instances.Add(instance); 952 instances.Add(instance);
@@ -913,9 +962,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
913 assembly = m_Assemblies[i.AssetID]; 962 assembly = m_Assemblies[i.AssetID];
914 963
915 964
965>>>>>>> avn/ubitvar
916 try 966 try
917 { 967 {
918 i.SaveState(assembly); 968 i.SaveState();
919 } 969 }
920 catch (Exception e) 970 catch (Exception e)
921 { 971 {
@@ -927,8 +977,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
927 } 977 }
928 } 978 }
929 979
930 instances.Clear();
931
932 if (saveTime > 0) 980 if (saveTime > 0)
933 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), 981 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup),
934 new Object[] { saveTime }); 982 new Object[] { saveTime });
@@ -938,6 +986,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
938 986
939 public void SaveAllState() 987 public void SaveAllState()
940 { 988 {
989 DoBackup(new object[] { 0 });
990 }
991
992 public object DoMaintenance(object p)
993 {
994 object[] parms = (object[])p;
995 int sleepTime = (int)parms[0];
996
941 foreach (IScriptInstance inst in m_Scripts.Values) 997 foreach (IScriptInstance inst in m_Scripts.Values)
942 { 998 {
943 if (inst.EventTime() > m_EventLimit) 999 if (inst.EventTime() > m_EventLimit)
@@ -947,14 +1003,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
947 inst.Start(); 1003 inst.Start();
948 } 1004 }
949 } 1005 }
950 }
951
952 public object DoMaintenance(object p)
953 {
954 object[] parms = (object[])p;
955 int sleepTime = (int)parms[0];
956
957 SaveAllState();
958 1006
959 System.Threading.Thread.Sleep(sleepTime); 1007 System.Threading.Thread.Sleep(sleepTime);
960 1008
@@ -1032,8 +1080,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1032 if (restOfFirstLine.StartsWith("c#") 1080 if (restOfFirstLine.StartsWith("c#")
1033 || restOfFirstLine.StartsWith("vb") 1081 || restOfFirstLine.StartsWith("vb")
1034 || restOfFirstLine.StartsWith("lsl") 1082 || restOfFirstLine.StartsWith("lsl")
1035 || restOfFirstLine.StartsWith("js")
1036 || restOfFirstLine.StartsWith("yp")
1037 || restOfFirstLine.Length == 0) 1083 || restOfFirstLine.Length == 0)
1038 warnRunningInXEngine = true; 1084 warnRunningInXEngine = true;
1039 1085
@@ -1067,12 +1113,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1067 if (engine != ScriptEngineName) 1113 if (engine != ScriptEngineName)
1068 return; 1114 return;
1069 1115
1070 // If we've seen this exact script text before, use that reference instead
1071 if (m_uniqueScripts.ContainsKey(script))
1072 script = m_uniqueScripts[script];
1073 else
1074 m_uniqueScripts[script] = script;
1075
1076 Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource}; 1116 Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource};
1077 1117
1078 if (stateSource == (int)StateSource.ScriptedRez) 1118 if (stateSource == (int)StateSource.ScriptedRez)
@@ -1086,11 +1126,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1086 } 1126 }
1087 else 1127 else
1088 { 1128 {
1089 m_CompileQueue.Enqueue(parms);
1090 lock (m_CompileDict) 1129 lock (m_CompileDict)
1091 {
1092 m_CompileDict[itemID] = 0; 1130 m_CompileDict[itemID] = 0;
1093 } 1131
1132 // This must occur after the m_CompileDict so that an existing compile thread cannot hit the check
1133 // in DoOnRezScript() before m_CompileDict has been updated.
1134 m_CompileQueue.Enqueue(parms);
1094 1135
1095// m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID); 1136// m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID);
1096 1137
@@ -1112,49 +1153,81 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1112 1153
1113 public Object DoOnRezScriptQueue(Object dummy) 1154 public Object DoOnRezScriptQueue(Object dummy)
1114 { 1155 {
1115 if (m_InitialStartup) 1156 try
1116 { 1157 {
1117 // This delay exists to stop mono problems where script compilation and startup would stop the sim 1158 if (m_InitialStartup)
1118 // working properly for the session. 1159 {
1119 System.Threading.Thread.Sleep(m_StartDelay); 1160 // This delay exists to stop mono problems where script compilation and startup would stop the sim
1161 // working properly for the session.
1162 System.Threading.Thread.Sleep(m_StartDelay);
1120 1163
1121 m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name); 1164 m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name);
1122 } 1165 }
1123 1166
1124 object[] o; 1167 object[] o;
1125 1168
1126 int scriptsStarted = 0; 1169 int scriptsStarted = 0;
1127 1170
1128 while (m_CompileQueue.Dequeue(out o)) 1171 while (m_CompileQueue.Dequeue(out o))
1129 {
1130 if (DoOnRezScript(o))
1131 { 1172 {
1132 scriptsStarted++; 1173 try
1174 {
1175 if (DoOnRezScript(o))
1176 {
1177 scriptsStarted++;
1133 1178
1134 if (m_InitialStartup) 1179 if (m_InitialStartup)
1135 if (scriptsStarted % 50 == 0) 1180 if (scriptsStarted % 50 == 0)
1136 m_log.InfoFormat( 1181 m_log.InfoFormat(
1137 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); 1182 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name);
1183 }
1184 }
1185 catch (Exception e)
1186 {
1187 m_log.Error(
1188 string.Format(
1189 "[XEngine]: Failure in DoOnRezScriptQueue() for item {0} in {1}. Continuing. Exception ",
1190 o[1], m_Scene.Name),
1191 e);
1192 }
1138 } 1193 }
1139 }
1140 1194
1141 if (m_InitialStartup) 1195 if (m_InitialStartup)
1142 m_log.InfoFormat( 1196 m_log.InfoFormat(
1143 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name); 1197 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name);
1144 1198
1145 // NOTE: Despite having a lockless queue, this lock is required 1199 }
1146 // to make sure there is never no compile thread while there 1200 catch (Exception e)
1147 // are still scripts to compile. This could otherwise happen 1201 {
1148 // due to a race condition 1202 m_log.Error(
1149 // 1203 string.Format("[XEngine]: Failure in DoOnRezScriptQueue() in {0}. Exception ", m_Scene.Name), e);
1150 lock (m_CompileQueue) 1204 }
1151 m_CurrentCompile = null; 1205 finally
1206 {
1207 // FIXME: On failure we must trigger this even if the compile queue is not actually empty so that the
1208 // RegionReadyModule is not forever waiting. This event really needs a different name.
1209 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount,
1210 m_ScriptErrorMessage);
1152 1211
1153 m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount, 1212 m_ScriptFailCount = 0;
1154 m_ScriptErrorMessage); 1213 m_InitialStartup = false;
1155 1214
1156 m_ScriptFailCount = 0; 1215 // NOTE: Despite having a lockless queue, this lock is required
1157 m_InitialStartup = false; 1216 // to make sure there is never no compile thread while there
1217 // are still scripts to compile. This could otherwise happen
1218 // due to a race condition
1219 //
1220 lock (m_CompileQueue)
1221 {
1222 m_CurrentCompile = null;
1223
1224 // This is to avoid a situation where the m_CompileQueue while loop above could complete but
1225 // OnRezScript() place a new script on the queue and check m_CurrentCompile = null before we hit
1226 // this section.
1227 if (m_CompileQueue.Count > 0)
1228 m_CurrentCompile = m_ThreadPool.QueueWorkItem(DoOnRezScriptQueue, null);
1229 }
1230 }
1158 1231
1159 return null; 1232 return null;
1160 } 1233 }
@@ -1201,16 +1274,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1201 return false; 1274 return false;
1202 } 1275 }
1203 1276
1204 m_log.DebugFormat( 1277 if (DebugLevel > 0)
1205 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1278 m_log.DebugFormat(
1206 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1279 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1207 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1280 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1281 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1208 1282
1209 UUID assetID = item.AssetID; 1283 UUID assetID = item.AssetID;
1210 1284
1211 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); 1285 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
1212 1286
1213 string assembly = ""; 1287 string assemblyPath = "";
1214 1288
1215 Culture.SetCurrentCulture(); 1289 Culture.SetCurrentCulture();
1216 1290
@@ -1222,12 +1296,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1222 { 1296 {
1223 lock (m_AddingAssemblies) 1297 lock (m_AddingAssemblies)
1224 { 1298 {
1225 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap); 1299 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assemblyPath, out linemap);
1226 1300
1227 if (!m_AddingAssemblies.ContainsKey(assembly)) { 1301// m_log.DebugFormat(
1228 m_AddingAssemblies[assembly] = 1; 1302// "[XENGINE]: Found assembly path {0} onrez {1} in {2}",
1303// assemblyPath, item.ItemID, World.Name);
1304
1305 if (!m_AddingAssemblies.ContainsKey(assemblyPath)) {
1306 m_AddingAssemblies[assemblyPath] = 1;
1229 } else { 1307 } else {
1230 m_AddingAssemblies[assembly]++; 1308 m_AddingAssemblies[assemblyPath]++;
1231 } 1309 }
1232 } 1310 }
1233 1311
@@ -1387,11 +1465,156 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1387 } 1465 }
1388 else 1466 else
1389 { 1467 {
1468<<<<<<< HEAD
1469 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1470 m_ScriptErrorMessage += "Exception creating app domain:\n";
1471 m_ScriptFailCount++;
1472 lock (m_AddingAssemblies)
1473 {
1474 m_AddingAssemblies[assemblyPath]--;
1475 }
1476 return false;
1477=======
1390 sandbox = AppDomain.CurrentDomain; 1478 sandbox = AppDomain.CurrentDomain;
1479>>>>>>> avn/ubitvar
1480 }
1481
1482<<<<<<< HEAD
1483 IScript scriptObj = null;
1484 EventWaitHandle coopSleepHandle;
1485 bool coopTerminationForThisScript;
1486
1487 // Set up assembly name to point to the appropriate scriptEngines directory
1488 AssemblyName assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(assemblyPath));
1489 assemblyName.CodeBase = Path.GetDirectoryName(assemblyPath);
1490
1491 if (m_coopTermination)
1492 {
1493 try
1494 {
1495 coopSleepHandle = new XEngineEventWaitHandle(false, EventResetMode.AutoReset);
1496
1497 scriptObj
1498 = (IScript)m_AppDomains[appDomain].CreateInstanceAndUnwrap(
1499 assemblyName.FullName,
1500 "SecondLife.XEngineScript",
1501 false,
1502 BindingFlags.Default,
1503 null,
1504 new object[] { coopSleepHandle },
1505 null,
1506 null);
1507
1508 coopTerminationForThisScript = true;
1509 }
1510 catch (TypeLoadException)
1511 {
1512 coopSleepHandle = null;
1513
1514 try
1515 {
1516 scriptObj
1517 = (IScript)m_AppDomains[appDomain].CreateInstanceAndUnwrap(
1518 assemblyName.FullName,
1519 "SecondLife.Script",
1520 false,
1521 BindingFlags.Default,
1522 null,
1523 null,
1524 null,
1525 null);
1526 }
1527 catch (Exception e2)
1528 {
1529 m_log.Error(
1530 string.Format(
1531 "[XENGINE]: Could not load previous SecondLife.Script from assembly {0} in {1}. Not starting. Exception ",
1532 assemblyName.FullName, World.Name),
1533 e2);
1534
1535 return false;
1536 }
1537
1538 coopTerminationForThisScript = false;
1539 }
1540 }
1541 else
1542 {
1543 try
1544 {
1545 scriptObj
1546 = (IScript)m_AppDomains[appDomain].CreateInstanceAndUnwrap(
1547 assemblyName.FullName,
1548 "SecondLife.Script",
1549 false,
1550 BindingFlags.Default,
1551 null,
1552 null,
1553 null,
1554 null);
1555
1556 coopSleepHandle = null;
1557 coopTerminationForThisScript = false;
1391 } 1558 }
1559 catch (TypeLoadException)
1560 {
1561 coopSleepHandle = new XEngineEventWaitHandle(false, EventResetMode.AutoReset);
1562
1563 try
1564 {
1565 scriptObj
1566 = (IScript)m_AppDomains[appDomain].CreateInstanceAndUnwrap(
1567 assemblyName.FullName,
1568 "SecondLife.XEngineScript",
1569 false,
1570 BindingFlags.Default,
1571 null,
1572 new object[] { coopSleepHandle },
1573 null,
1574 null);
1575 }
1576 catch (Exception e2)
1577 {
1578 m_log.Error(
1579 string.Format(
1580 "[XENGINE]: Could not load previous SecondLife.XEngineScript from assembly {0} in {1}. Not starting. Exception ",
1581 assemblyName.FullName, World.Name),
1582 e2);
1583
1584 return false;
1585 }
1586
1587 coopTerminationForThisScript = true;
1588 }
1589 }
1392 1590
1591 if (m_coopTermination != coopTerminationForThisScript && !HaveNotifiedLogOfScriptStopMistmatch)
1592 {
1593 // Notify the log that there is at least one script compile that doesn't match the
1594 // ScriptStopStrategy. Operator has to manually delete old DLLs - we can't do this on Windows
1595 // once the assembly has been loaded evne if the instantiation of a class was unsuccessful.
1596 m_log.WarnFormat(
1597 "[XEngine]: At least one existing compiled script DLL in {0} has {1} as ScriptStopStrategy whereas config setting is {2}."
1598 + "\nContinuing with script compiled strategy but to remove this message please set [XEngine] DeleteScriptsOnStartup = true for one simulator session to remove old script DLLs (script state will not be lost).",
1599 World.Name, coopTerminationForThisScript ? "co-op" : "abort", m_coopTermination ? "co-op" : "abort");
1600
1601 HaveNotifiedLogOfScriptStopMistmatch = true;
1602 }
1603
1604 instance = new ScriptInstance(this, part,
1605 item,
1606 startParam, postOnRez,
1607 m_MaxScriptQueue);
1608
1609 if (
1610 !instance.Load(
1611 scriptObj, coopSleepHandle, assemblyPath,
1612 Path.Combine(ScriptEnginePath, World.RegionInfo.RegionID.ToString()), stateSource, coopTerminationForThisScript))
1613 return false;
1614=======
1393// if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource)) 1615// if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource))
1394// return false; 1616// return false;
1617>>>>>>> avn/ubitvar
1395 1618
1396 m_AppDomains[appDomain] = sandbox; 1619 m_AppDomains[appDomain] = sandbox;
1397 1620
@@ -1444,11 +1667,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1444 } 1667 }
1445 1668
1446 if (!m_Assemblies.ContainsKey(assetID)) 1669 if (!m_Assemblies.ContainsKey(assetID))
1447 m_Assemblies[assetID] = assembly; 1670 m_Assemblies[assetID] = assemblyPath;
1448 1671
1449 lock (m_AddingAssemblies) 1672 lock (m_AddingAssemblies)
1450 { 1673 {
1451 m_AddingAssemblies[assembly]--; 1674 m_AddingAssemblies[assemblyPath]--;
1452 } 1675 }
1453 1676
1454 if (instance!=null) 1677 if (instance!=null)
@@ -1482,6 +1705,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1482 return; 1705 return;
1483 } 1706 }
1484 1707
1708<<<<<<< HEAD
1709 instance.Stop(m_WaitForEventCompletionOnScriptStop, true);
1710=======
1485 IScriptInstance instance=m_Scripts[itemID]; 1711 IScriptInstance instance=m_Scripts[itemID];
1486 lockScriptsForRead(false); 1712 lockScriptsForRead(false);
1487 lockScriptsForWrite(true); 1713 lockScriptsForWrite(true);
@@ -1492,6 +1718,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1492 instance.Stop(m_WaitForEventCompletionOnScriptStop); 1718 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1493 1719
1494// bool objectRemoved = false; 1720// bool objectRemoved = false;
1721>>>>>>> avn/ubitvar
1495 1722
1496 lock (m_PrimObjects) 1723 lock (m_PrimObjects)
1497 { 1724 {
@@ -1504,14 +1731,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1504 1731
1505 // If there are no more scripts, remove prim 1732 // If there are no more scripts, remove prim
1506 if (m_PrimObjects[localID].Count == 0) 1733 if (m_PrimObjects[localID].Count == 0)
1507 {
1508 m_PrimObjects.Remove(localID); 1734 m_PrimObjects.Remove(localID);
1509// objectRemoved = true;
1510 }
1511 } 1735 }
1512 } 1736 }
1513 1737
1514 instance.RemoveState(); 1738 if (instance.StatePersistedHere)
1739 instance.RemoveState();
1740
1515 instance.DestroyScriptInstance(); 1741 instance.DestroyScriptInstance();
1516 1742
1517 if (m_DomainScripts.ContainsKey(instance.AppDomain)) 1743 if (m_DomainScripts.ContainsKey(instance.AppDomain))
@@ -1653,7 +1879,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1653 1879
1654 IScriptInstance instance = (ScriptInstance) parms; 1880 IScriptInstance instance = (ScriptInstance) parms;
1655 1881
1656 //m_log.DebugFormat("[XEngine]: Processing event for {0}", instance); 1882// m_log.DebugFormat("[XEngine]: Processing event for {0}", instance);
1657 1883
1658 return instance.EventProcessor(); 1884 return instance.EventProcessor();
1659 } 1885 }
@@ -1829,6 +2055,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1829 IScriptInstance instance = GetInstance(itemID); 2055 IScriptInstance instance = GetInstance(itemID);
1830 if (instance != null) 2056 if (instance != null)
1831 instance.ApiResetScript(); 2057 instance.ApiResetScript();
2058
2059 // Send the new number of threads that are in use by the thread
2060 // pool, I believe that by adding them to the locations where the
2061 // script is changing states that I will catch all changes to the
2062 // thread pool
2063 m_Scene.setThreadCount(m_ThreadPool.InUseThreads);
1832 } 2064 }
1833 2065
1834 public void ResetScript(UUID itemID) 2066 public void ResetScript(UUID itemID)
@@ -1836,6 +2068,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1836 IScriptInstance instance = GetInstance(itemID); 2068 IScriptInstance instance = GetInstance(itemID);
1837 if (instance != null) 2069 if (instance != null)
1838 instance.ResetScript(m_WaitForEventCompletionOnScriptStop); 2070 instance.ResetScript(m_WaitForEventCompletionOnScriptStop);
2071
2072 // Send the new number of threads that are in use by the thread
2073 // pool, I believe that by adding them to the locations where the
2074 // script is changing states that I will catch all changes to the
2075 // thread pool
2076 m_Scene.setThreadCount(m_ThreadPool.InUseThreads);
1839 } 2077 }
1840 2078
1841 public void StartScript(UUID itemID) 2079 public void StartScript(UUID itemID)
@@ -1845,6 +2083,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1845 instance.Start(); 2083 instance.Start();
1846 else 2084 else
1847 m_runFlags.AddOrUpdate(itemID, true, 240); 2085 m_runFlags.AddOrUpdate(itemID, true, 240);
2086
2087 // Send the new number of threads that are in use by the thread
2088 // pool, I believe that by adding them to the locations where the
2089 // script is changing states that I will catch all changes to the
2090 // thread pool
2091 m_Scene.setThreadCount(m_ThreadPool.InUseThreads);
1848 } 2092 }
1849 2093
1850 public void StopScript(UUID itemID) 2094 public void StopScript(UUID itemID)
@@ -1853,6 +2097,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1853 2097
1854 if (instance != null) 2098 if (instance != null)
1855 { 2099 {
2100 lock (instance.EventQueue)
2101 instance.StayStopped = true; // the script was stopped explicitly
2102
1856 instance.Stop(m_WaitForEventCompletionOnScriptStop); 2103 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1857 } 2104 }
1858 else 2105 else
@@ -1860,6 +2107,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1860// m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name); 2107// m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name);
1861 m_runFlags.AddOrUpdate(itemID, false, 240); 2108 m_runFlags.AddOrUpdate(itemID, false, 240);
1862 } 2109 }
2110
2111 // Send the new number of threads that are in use by the thread
2112 // pool, I believe that by adding them to the locations where the
2113 // script is changing states that I will catch all changes to the
2114 // thread pool
2115 m_Scene.setThreadCount(m_ThreadPool.InUseThreads);
1863 } 2116 }
1864 2117
1865 public DetectParams GetDetectParams(UUID itemID, int idx) 2118 public DetectParams GetDetectParams(UUID itemID, int idx)
@@ -2225,7 +2478,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2225 catch (IOException ex) 2478 catch (IOException ex)
2226 { 2479 {
2227 // if there already exists a file at that location, it may be locked. 2480 // if there already exists a file at that location, it may be locked.
2228 m_log.ErrorFormat("[XEngine]: Linemap file {0} already exists! {1}", mappath, ex.Message); 2481 m_log.Error(
2482 string.Format("[XEngine]: Linemap file {0} could not be written. Exception ", mappath), ex);
2229 } 2483 }
2230 } 2484 }
2231 } 2485 }
@@ -2251,6 +2505,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2251 m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message); 2505 m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message);
2252 } 2506 }
2253 2507
2508// m_log.DebugFormat(
2509// "[XEngine]: Wrote state for script item with ID {0} at {1} in {2}", itemID, statepath, m_Scene.Name);
2510
2254 return true; 2511 return true;
2255 } 2512 }
2256 2513
@@ -2272,7 +2529,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2272 2529
2273 public Dictionary<uint, float> GetObjectScriptsExecutionTimes() 2530 public Dictionary<uint, float> GetObjectScriptsExecutionTimes()
2274 { 2531 {
2275 long tickNow = Util.EnvironmentTickCount();
2276 Dictionary<uint, float> topScripts = new Dictionary<uint, float>(); 2532 Dictionary<uint, float> topScripts = new Dictionary<uint, float>();
2277 2533
2278 lock (m_Scripts) 2534 lock (m_Scripts)
@@ -2282,7 +2538,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2282 if (!topScripts.ContainsKey(si.LocalID)) 2538 if (!topScripts.ContainsKey(si.LocalID))
2283 topScripts[si.RootLocalID] = 0; 2539 topScripts[si.RootLocalID] = 0;
2284 2540
2285 topScripts[si.RootLocalID] += CalculateAdjustedExectionTime(si, tickNow); 2541 topScripts[si.RootLocalID] += GetExectionTime(si);
2286 } 2542 }
2287 } 2543 }
2288 2544
@@ -2296,7 +2552,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2296 return 0.0f; 2552 return 0.0f;
2297 } 2553 }
2298 float time = 0.0f; 2554 float time = 0.0f;
2299 long tickNow = Util.EnvironmentTickCount();
2300 IScriptInstance si; 2555 IScriptInstance si;
2301 // Calculate the time for all scripts that this engine is executing 2556 // Calculate the time for all scripts that this engine is executing
2302 // Ignore any others 2557 // Ignore any others
@@ -2305,36 +2560,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2305 si = GetInstance(id); 2560 si = GetInstance(id);
2306 if (si != null && si.Running) 2561 if (si != null && si.Running)
2307 { 2562 {
2308 time += CalculateAdjustedExectionTime(si, tickNow); 2563 time += GetExectionTime(si);
2309 } 2564 }
2310 } 2565 }
2311 return time; 2566 return time;
2312 } 2567 }
2313 2568
2314 private float CalculateAdjustedExectionTime(IScriptInstance si, long tickNow) 2569 private float GetExectionTime(IScriptInstance si)
2315 { 2570 {
2316 long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; 2571 return (float)si.ExecutionTime.GetSumTime().TotalMilliseconds;
2317
2318 // Avoid divide by zero
2319 if (ticksElapsed == 0)
2320 ticksElapsed = 1;
2321
2322 // Scale execution time to the ideal 55 fps frame time for these reasons.
2323 //
2324 // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
2325 // 'script execution time per frame', which is the original purpose of this value.
2326 //
2327 // 2) Giving the raw execution times is misleading since scripts start at different times, making
2328 // it impossible to compare scripts.
2329 //
2330 // 3) Scaling the raw execution time to the time that the script has been running is better but
2331 // is still misleading since a script that has just been rezzed may appear to have been running
2332 // for much longer.
2333 //
2334 // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
2335 // since the figure does not represent actual execution time and very hard running scripts will
2336 // never exceed 18ms (though this is a very high number for script execution so is a warning sign).
2337 return ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
2338 } 2572 }
2339 2573
2340 public void SuspendScript(UUID itemID) 2574 public void SuspendScript(UUID itemID)
@@ -2346,6 +2580,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2346 instance.Suspend(); 2580 instance.Suspend();
2347// else 2581// else
2348// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 2582// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
2583
2584 // Send the new number of threads that are in use by the thread
2585 // pool, I believe that by adding them to the locations where the
2586 // script is changing states that I will catch all changes to the
2587 // thread pool
2588 m_Scene.setThreadCount(m_ThreadPool.InUseThreads);
2349 } 2589 }
2350 2590
2351 public void ResumeScript(UUID itemID) 2591 public void ResumeScript(UUID itemID)
@@ -2357,6 +2597,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2357 instance.Resume(); 2597 instance.Resume();
2358// else 2598// else
2359// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 2599// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
2600
2601 // Send the new number of threads that are in use by the thread
2602 // pool, I believe that by adding them to the locations where the
2603 // script is changing states that I will catch all changes to the
2604 // thread pool
2605 m_Scene.setThreadCount(m_ThreadPool.InUseThreads);
2360 } 2606 }
2361 2607
2362 public bool HasScript(UUID itemID, out bool running) 2608 public bool HasScript(UUID itemID, out bool running)
@@ -2370,5 +2616,30 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2370 running = instance.Running; 2616 running = instance.Running;
2371 return true; 2617 return true;
2372 } 2618 }
2619
2620 public void SleepScript(UUID itemID, int delay)
2621 {
2622 IScriptInstance instance = GetInstance(itemID);
2623 if (instance == null)
2624 return;
2625
2626 instance.ExecutionTimer.Stop();
2627 try
2628 {
2629 if (instance.CoopWaitHandle != null)
2630 {
2631 if (instance.CoopWaitHandle.WaitOne(delay))
2632 throw new ScriptCoopStopException();
2633 }
2634 else
2635 {
2636 Thread.Sleep(delay);
2637 }
2638 }
2639 finally
2640 {
2641 instance.ExecutionTimer.Start();
2642 }
2643 }
2373 } 2644 }
2374} 2645}