diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine/XEngine.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 116 |
1 files changed, 96 insertions, 20 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index c68f03f..7712076 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -49,7 +49,10 @@ using OpenSim.Region.ScriptEngine.Shared; | |||
49 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | 49 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; |
50 | using OpenSim.Region.ScriptEngine.Shared.CodeTools; | 50 | using OpenSim.Region.ScriptEngine.Shared.CodeTools; |
51 | using OpenSim.Region.ScriptEngine.Shared.Instance; | 51 | using OpenSim.Region.ScriptEngine.Shared.Instance; |
52 | using OpenSim.Region.ScriptEngine.Shared.Api; | ||
53 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; | ||
52 | using OpenSim.Region.ScriptEngine.Interfaces; | 54 | using OpenSim.Region.ScriptEngine.Interfaces; |
55 | using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; | ||
53 | 56 | ||
54 | using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; | 57 | using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; |
55 | 58 | ||
@@ -173,12 +176,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
173 | get { return m_ConfigSource; } | 176 | get { return m_ConfigSource; } |
174 | } | 177 | } |
175 | 178 | ||
179 | /// <summary> | ||
180 | /// Event fired after the script engine has finished removing a script. | ||
181 | /// </summary> | ||
176 | public event ScriptRemoved OnScriptRemoved; | 182 | public event ScriptRemoved OnScriptRemoved; |
183 | |||
184 | /// <summary> | ||
185 | /// Event fired after the script engine has finished removing a script from an object. | ||
186 | /// </summary> | ||
177 | public event ObjectRemoved OnObjectRemoved; | 187 | public event ObjectRemoved OnObjectRemoved; |
178 | 188 | ||
179 | // | ||
180 | // IRegionModule functions | ||
181 | // | ||
182 | public void Initialise(IConfigSource configSource) | 189 | public void Initialise(IConfigSource configSource) |
183 | { | 190 | { |
184 | if (configSource.Configs["XEngine"] == null) | 191 | if (configSource.Configs["XEngine"] == null) |
@@ -274,22 +281,22 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
274 | } | 281 | } |
275 | 282 | ||
276 | MainConsole.Instance.Commands.AddCommand( | 283 | MainConsole.Instance.Commands.AddCommand( |
277 | "scripts", false, "xengine status", "xengine status", "Show status information", | 284 | "Scripts", false, "xengine status", "xengine status", "Show status information", |
278 | "Show status information on the script engine.", | 285 | "Show status information on the script engine.", |
279 | HandleShowStatus); | 286 | HandleShowStatus); |
280 | 287 | ||
281 | MainConsole.Instance.Commands.AddCommand( | 288 | MainConsole.Instance.Commands.AddCommand( |
282 | "scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", | 289 | "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", |
283 | "Show information on all scripts known to the script engine." | 290 | "Show information on all scripts known to the script engine." |
284 | + "If a <script-item-uuid> is given then only information on that script will be shown.", | 291 | + "If a <script-item-uuid> is given then only information on that script will be shown.", |
285 | HandleShowScripts); | 292 | HandleShowScripts); |
286 | 293 | ||
287 | MainConsole.Instance.Commands.AddCommand( | 294 | MainConsole.Instance.Commands.AddCommand( |
288 | "scripts", false, "show scripts", "show scripts [<script-item-uuid>]", "Show script information", | 295 | "Scripts", false, "show scripts", "show scripts [<script-item-uuid>]", "Show script information", |
289 | "Synonym for scripts show command", HandleShowScripts); | 296 | "Synonym for scripts show command", HandleShowScripts); |
290 | 297 | ||
291 | MainConsole.Instance.Commands.AddCommand( | 298 | MainConsole.Instance.Commands.AddCommand( |
292 | "scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>]", "Suspends all running scripts", | 299 | "Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>]", "Suspends all running scripts", |
293 | "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a" | 300 | "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a" |
294 | + " script that is currently processing an event.\n" | 301 | + " script that is currently processing an event.\n" |
295 | + "Suspended scripts will continue to accumulate events but won't process them.\n" | 302 | + "Suspended scripts will continue to accumulate events but won't process them.\n" |
@@ -297,20 +304,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
297 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript)); | 304 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript)); |
298 | 305 | ||
299 | MainConsole.Instance.Commands.AddCommand( | 306 | MainConsole.Instance.Commands.AddCommand( |
300 | "scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", | 307 | "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", |
301 | "Resumes all currently suspended scripts.\n" | 308 | "Resumes all currently suspended scripts.\n" |
302 | + "Resumed scripts will process all events accumulated whilst suspended." | 309 | + "Resumed scripts will process all events accumulated whilst suspended." |
303 | + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", | 310 | + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", |
304 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); | 311 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); |
305 | 312 | ||
306 | MainConsole.Instance.Commands.AddCommand( | 313 | MainConsole.Instance.Commands.AddCommand( |
307 | "scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", | 314 | "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", |
308 | "Stops all running scripts." | 315 | "Stops all running scripts." |
309 | + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", | 316 | + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", |
310 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); | 317 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); |
311 | 318 | ||
312 | MainConsole.Instance.Commands.AddCommand( | 319 | MainConsole.Instance.Commands.AddCommand( |
313 | "scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", | 320 | "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", |
314 | "Starts all stopped scripts." | 321 | "Starts all stopped scripts." |
315 | + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", | 322 | + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", |
316 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); | 323 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); |
@@ -373,6 +380,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
373 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) | 380 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) |
374 | return; | 381 | return; |
375 | 382 | ||
383 | MainConsole.Instance.OutputFormat(GetStatusReport()); | ||
384 | } | ||
385 | |||
386 | public string GetStatusReport() | ||
387 | { | ||
376 | StringBuilder sb = new StringBuilder(); | 388 | StringBuilder sb = new StringBuilder(); |
377 | sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); | 389 | sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); |
378 | 390 | ||
@@ -381,12 +393,26 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
381 | 393 | ||
382 | sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); | 394 | sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); |
383 | sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); | 395 | sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); |
396 | sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); | ||
397 | sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads); | ||
384 | sb.AppendFormat("Allocated threads : {0}\n", m_ThreadPool.ActiveThreads); | 398 | sb.AppendFormat("Allocated threads : {0}\n", m_ThreadPool.ActiveThreads); |
385 | sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); | 399 | sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); |
386 | sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); | 400 | sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); |
387 | // sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); | 401 | // sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); |
388 | 402 | ||
389 | MainConsole.Instance.OutputFormat(sb.ToString()); | 403 | SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); |
404 | sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); | ||
405 | |||
406 | Dataserver ds = AsyncCommandManager.GetDataserverPlugin(this); | ||
407 | sb.AppendFormat("Dataserver requests : {0}\n", ds != null ? ds.DataserverRequestsCount : 0); | ||
408 | |||
409 | Timer t = AsyncCommandManager.GetTimerPlugin(this); | ||
410 | sb.AppendFormat("Timers : {0}\n", t != null ? t.TimersCount : 0); | ||
411 | |||
412 | Listener l = AsyncCommandManager.GetListenerPlugin(this); | ||
413 | sb.AppendFormat("Listeners : {0}\n", l != null ? l.ListenerCount : 0); | ||
414 | |||
415 | return sb.ToString(); | ||
390 | } | 416 | } |
391 | 417 | ||
392 | public void HandleShowScripts(string module, string[] cmdparams) | 418 | public void HandleShowScripts(string module, string[] cmdparams) |
@@ -973,7 +999,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
973 | lock (m_Scripts) | 999 | lock (m_Scripts) |
974 | { | 1000 | { |
975 | // Create the object record | 1001 | // Create the object record |
976 | |||
977 | if ((!m_Scripts.ContainsKey(itemID)) || | 1002 | if ((!m_Scripts.ContainsKey(itemID)) || |
978 | (m_Scripts[itemID].AssetID != assetID)) | 1003 | (m_Scripts[itemID].AssetID != assetID)) |
979 | { | 1004 | { |
@@ -1063,7 +1088,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1063 | 1088 | ||
1064 | if (!m_PrimObjects[localID].Contains(itemID)) | 1089 | if (!m_PrimObjects[localID].Contains(itemID)) |
1065 | m_PrimObjects[localID].Add(itemID); | 1090 | m_PrimObjects[localID].Add(itemID); |
1066 | |||
1067 | } | 1091 | } |
1068 | 1092 | ||
1069 | if (!m_Assemblies.ContainsKey(assetID)) | 1093 | if (!m_Assemblies.ContainsKey(assetID)) |
@@ -1102,7 +1126,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1102 | } | 1126 | } |
1103 | 1127 | ||
1104 | instance.ClearQueue(); | 1128 | instance.ClearQueue(); |
1105 | instance.Stop(0); | 1129 | |
1130 | // Give the script some time to finish processing its last event. Simply aborting the script thread can | ||
1131 | // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. | ||
1132 | instance.Stop(1000); | ||
1133 | |||
1106 | // bool objectRemoved = false; | 1134 | // bool objectRemoved = false; |
1107 | 1135 | ||
1108 | lock (m_PrimObjects) | 1136 | lock (m_PrimObjects) |
@@ -1133,14 +1161,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1133 | UnloadAppDomain(instance.AppDomain); | 1161 | UnloadAppDomain(instance.AppDomain); |
1134 | } | 1162 | } |
1135 | 1163 | ||
1136 | instance = null; | ||
1137 | |||
1138 | ObjectRemoved handlerObjectRemoved = OnObjectRemoved; | 1164 | ObjectRemoved handlerObjectRemoved = OnObjectRemoved; |
1139 | if (handlerObjectRemoved != null) | 1165 | if (handlerObjectRemoved != null) |
1140 | { | 1166 | handlerObjectRemoved(instance.ObjectID); |
1141 | SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); | ||
1142 | handlerObjectRemoved(part.UUID); | ||
1143 | } | ||
1144 | 1167 | ||
1145 | ScriptRemoved handlerScriptRemoved = OnScriptRemoved; | 1168 | ScriptRemoved handlerScriptRemoved = OnScriptRemoved; |
1146 | if (handlerScriptRemoved != null) | 1169 | if (handlerScriptRemoved != null) |
@@ -1872,6 +1895,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1872 | } | 1895 | } |
1873 | } | 1896 | } |
1874 | 1897 | ||
1898 | public Dictionary<uint, float> GetObjectScriptsExecutionTimes() | ||
1899 | { | ||
1900 | long tickNow = Util.EnvironmentTickCount(); | ||
1901 | Dictionary<uint, float> topScripts = new Dictionary<uint, float>(); | ||
1902 | |||
1903 | lock (m_Scripts) | ||
1904 | { | ||
1905 | foreach (IScriptInstance si in m_Scripts.Values) | ||
1906 | { | ||
1907 | if (!topScripts.ContainsKey(si.LocalID)) | ||
1908 | topScripts[si.RootLocalID] = 0; | ||
1909 | |||
1910 | // long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; | ||
1911 | // float framesElapsed = ticksElapsed / (18.1818 * TimeSpan.TicksPerMillisecond); | ||
1912 | |||
1913 | // Execution time of the script adjusted by it's measurement period to make scripts started at | ||
1914 | // different times comparable. | ||
1915 | // float adjustedExecutionTime | ||
1916 | // = (float)si.MeasurementPeriodExecutionTime | ||
1917 | // / ((float)(tickNow - si.MeasurementPeriodTickStart) / ScriptInstance.MaxMeasurementPeriod) | ||
1918 | // / TimeSpan.TicksPerMillisecond; | ||
1919 | |||
1920 | long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; | ||
1921 | |||
1922 | // Avoid divide by zerp | ||
1923 | if (ticksElapsed == 0) | ||
1924 | ticksElapsed = 1; | ||
1925 | |||
1926 | // Scale execution time to the ideal 55 fps frame time for these reasons. | ||
1927 | // | ||
1928 | // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no | ||
1929 | // 'script execution time per frame', which is the original purpose of this value. | ||
1930 | // | ||
1931 | // 2) Giving the raw execution times is misleading since scripts start at different times, making | ||
1932 | // it impossible to compare scripts. | ||
1933 | // | ||
1934 | // 3) Scaling the raw execution time to the time that the script has been running is better but | ||
1935 | // is still misleading since a script that has just been rezzed may appear to have been running | ||
1936 | // for much longer. | ||
1937 | // | ||
1938 | // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect | ||
1939 | // since the figure does not represent actual execution time and very hard running scripts will | ||
1940 | // never exceed 18ms (though this is a very high number for script execution so is a warning sign). | ||
1941 | float adjustedExecutionTime | ||
1942 | = ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f; | ||
1943 | |||
1944 | topScripts[si.RootLocalID] += adjustedExecutionTime; | ||
1945 | } | ||
1946 | } | ||
1947 | |||
1948 | return topScripts; | ||
1949 | } | ||
1950 | |||
1875 | public void SuspendScript(UUID itemID) | 1951 | public void SuspendScript(UUID itemID) |
1876 | { | 1952 | { |
1877 | // m_log.DebugFormat("[XEngine]: Received request to suspend script with ID {0}", itemID); | 1953 | // m_log.DebugFormat("[XEngine]: Received request to suspend script with ID {0}", itemID); |