diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine/XEngine.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 355 |
1 files changed, 229 insertions, 126 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 1e0f01f..79d1944 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -63,6 +63,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
63 | { | 63 | { |
64 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 64 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
65 | 65 | ||
66 | /// <summary> | ||
67 | /// Control the printing of certain debug messages. | ||
68 | /// </summary> | ||
69 | /// <remarks> | ||
70 | /// If DebugLevel >= 1, then we log every time that a script is started. | ||
71 | /// </remarks> | ||
72 | // public int DebugLevel { get; set; } | ||
73 | |||
66 | private SmartThreadPool m_ThreadPool; | 74 | private SmartThreadPool m_ThreadPool; |
67 | private int m_MaxScriptQueue; | 75 | private int m_MaxScriptQueue; |
68 | private Scene m_Scene; | 76 | private Scene m_Scene; |
@@ -284,9 +292,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
284 | AppDomain.CurrentDomain.AssemblyResolve += | 292 | AppDomain.CurrentDomain.AssemblyResolve += |
285 | OnAssemblyResolve; | 293 | OnAssemblyResolve; |
286 | 294 | ||
287 | m_log.InfoFormat("[XEngine] Initializing scripts in region {0}", | ||
288 | scene.RegionInfo.RegionName); | ||
289 | m_Scene = scene; | 295 | m_Scene = scene; |
296 | m_log.InfoFormat("[XEngine]: Initializing scripts in region {0}", m_Scene.RegionInfo.RegionName); | ||
290 | 297 | ||
291 | m_MinThreads = m_ScriptConfig.GetInt("MinThreads", 2); | 298 | m_MinThreads = m_ScriptConfig.GetInt("MinThreads", 2); |
292 | m_MaxThreads = m_ScriptConfig.GetInt("MaxThreads", 100); | 299 | m_MaxThreads = m_ScriptConfig.GetInt("MaxThreads", 100); |
@@ -389,9 +396,42 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
389 | "Starts all stopped scripts." | 396 | "Starts all stopped scripts." |
390 | + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", | 397 | + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", |
391 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); | 398 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); |
399 | |||
400 | // MainConsole.Instance.Commands.AddCommand( | ||
401 | // "Debug", false, "debug xengine", "debug xengine [<level>]", | ||
402 | // "Turn on detailed xengine debugging.", | ||
403 | // "If level <= 0, then no extra logging is done.\n" | ||
404 | // + "If level >= 1, then we log every time that a script is started.", | ||
405 | // HandleDebugLevelCommand); | ||
392 | } | 406 | } |
393 | 407 | ||
394 | /// <summary> | 408 | /// <summary> |
409 | /// Change debug level | ||
410 | /// </summary> | ||
411 | /// <param name="module"></param> | ||
412 | /// <param name="args"></param> | ||
413 | // private void HandleDebugLevelCommand(string module, string[] args) | ||
414 | // { | ||
415 | // if (args.Length == 3) | ||
416 | // { | ||
417 | // int newDebug; | ||
418 | // if (int.TryParse(args[2], out newDebug)) | ||
419 | // { | ||
420 | // DebugLevel = newDebug; | ||
421 | // MainConsole.Instance.OutputFormat("Debug level set to {0}", newDebug); | ||
422 | // } | ||
423 | // } | ||
424 | // else if (args.Length == 2) | ||
425 | // { | ||
426 | // MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel); | ||
427 | // } | ||
428 | // else | ||
429 | // { | ||
430 | // MainConsole.Instance.Output("Usage: debug xengine 0..1"); | ||
431 | // } | ||
432 | // } | ||
433 | |||
434 | /// <summary> | ||
395 | /// Parse the raw item id into a script instance from the command params if it's present. | 435 | /// Parse the raw item id into a script instance from the command params if it's present. |
396 | /// </summary> | 436 | /// </summary> |
397 | /// <param name="cmdparams"></param> | 437 | /// <param name="cmdparams"></param> |
@@ -795,35 +835,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
795 | int colon = firstline.IndexOf(':'); | 835 | int colon = firstline.IndexOf(':'); |
796 | if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1) | 836 | if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1) |
797 | { | 837 | { |
798 | string engineName = firstline.Substring(2, colon-2); | 838 | string engineName = firstline.Substring(2, colon - 2); |
799 | 839 | ||
800 | if (names.Contains(engineName)) | 840 | if (names.Contains(engineName)) |
801 | { | 841 | { |
802 | engine = engineName; | 842 | engine = engineName; |
803 | script = "//" + script.Substring(script.IndexOf(':')+1); | 843 | script = "//" + script.Substring(colon + 1); |
804 | } | 844 | } |
805 | else | 845 | else |
806 | { | 846 | { |
807 | if (engine == ScriptEngineName) | 847 | if (engine == ScriptEngineName) |
808 | { | 848 | { |
809 | SceneObjectPart part = | 849 | // If we are falling back on XEngine as the default engine, then only complain to the user |
810 | m_Scene.GetSceneObjectPart( | 850 | // if a script language has been explicitly set and it's one that we recognize. If it's |
811 | localID); | 851 | // explicitly not allowed or the script is not in LSL then the user will be informed by a later compiler message. |
812 | 852 | // | |
813 | TaskInventoryItem item = | 853 | // This avoids the overwhelming number of false positives where we're in this code because |
814 | part.Inventory.GetInventoryItem(itemID); | 854 | // there's a colon in a comment in the first line of a script for entirely |
815 | 855 | // unrelated reasons (e.g. vim settings). | |
816 | ScenePresence presence = | 856 | // |
817 | m_Scene.GetScenePresence( | 857 | // TODO: A better fix would be to deprecate simple : detection and look for some less likely |
818 | item.OwnerID); | 858 | // string to begin the comment (like #! in unix shell scripts). |
819 | 859 | bool scriptExplicitlyInXEngineLanguage = false; | |
820 | if (presence != null) | 860 | string restOfScript = script.Substring(colon + 1); |
861 | |||
862 | // FIXME: These are hardcoded because they are currently hardcoded in Compiler.cs | ||
863 | if (restOfScript.StartsWith("c#") | ||
864 | || restOfScript.StartsWith("vb") | ||
865 | || restOfScript.StartsWith("lsl") | ||
866 | || restOfScript.StartsWith("js") | ||
867 | || restOfScript.StartsWith("yp")) | ||
868 | scriptExplicitlyInXEngineLanguage = true; | ||
869 | |||
870 | if (scriptExplicitlyInXEngineLanguage) | ||
821 | { | 871 | { |
822 | presence.ControllingClient.SendAgentAlertMessage( | 872 | SceneObjectPart part = |
823 | "Selected engine unavailable. "+ | 873 | m_Scene.GetSceneObjectPart( |
824 | "Running script on "+ | 874 | localID); |
825 | ScriptEngineName, | 875 | |
826 | false); | 876 | TaskInventoryItem item = |
877 | part.Inventory.GetInventoryItem(itemID); | ||
878 | |||
879 | ScenePresence presence = | ||
880 | m_Scene.GetScenePresence( | ||
881 | item.OwnerID); | ||
882 | |||
883 | if (presence != null) | ||
884 | { | ||
885 | presence.ControllingClient.SendAgentAlertMessage( | ||
886 | "Selected engine unavailable. "+ | ||
887 | "Running script on "+ | ||
888 | ScriptEngineName, | ||
889 | false); | ||
890 | } | ||
827 | } | 891 | } |
828 | } | 892 | } |
829 | } | 893 | } |
@@ -880,20 +944,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
880 | { | 944 | { |
881 | if (m_InitialStartup) | 945 | if (m_InitialStartup) |
882 | { | 946 | { |
883 | m_InitialStartup = false; | 947 | // This delay exists to stop mono problems where script compilation and startup would stop the sim |
948 | // working properly for the session. | ||
884 | System.Threading.Thread.Sleep(15000); | 949 | System.Threading.Thread.Sleep(15000); |
950 | } | ||
951 | |||
952 | object[] o; | ||
953 | |||
954 | int scriptsStarted = 0; | ||
885 | 955 | ||
886 | if (m_CompileQueue.Count == 0) | 956 | while (m_CompileQueue.Dequeue(out o)) |
957 | { | ||
958 | if (DoOnRezScript(o)) | ||
887 | { | 959 | { |
888 | // No scripts on region, so won't get triggered later | 960 | scriptsStarted++; |
889 | // by the queue becoming empty so we trigger it here | 961 | |
890 | m_Scene.EventManager.TriggerEmptyScriptCompileQueue(0, String.Empty); | 962 | if (m_InitialStartup) |
963 | if (scriptsStarted % 50 == 0) | ||
964 | m_log.InfoFormat( | ||
965 | "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); | ||
891 | } | 966 | } |
892 | } | 967 | } |
893 | 968 | ||
894 | object[] o; | 969 | if (m_InitialStartup) |
895 | while (m_CompileQueue.Dequeue(out o)) | 970 | m_log.InfoFormat( |
896 | DoOnRezScript(o); | 971 | "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); |
897 | 972 | ||
898 | // NOTE: Despite having a lockless queue, this lock is required | 973 | // NOTE: Despite having a lockless queue, this lock is required |
899 | // to make sure there is never no compile thread while there | 974 | // to make sure there is never no compile thread while there |
@@ -901,12 +976,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
901 | // due to a race condition | 976 | // due to a race condition |
902 | // | 977 | // |
903 | lock (m_CompileQueue) | 978 | lock (m_CompileQueue) |
904 | { | ||
905 | m_CurrentCompile = null; | 979 | m_CurrentCompile = null; |
906 | } | 980 | |
907 | m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount, | 981 | m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount, |
908 | m_ScriptErrorMessage); | 982 | m_ScriptErrorMessage); |
983 | |||
909 | m_ScriptFailCount = 0; | 984 | m_ScriptFailCount = 0; |
985 | m_InitialStartup = false; | ||
910 | 986 | ||
911 | return null; | 987 | return null; |
912 | } | 988 | } |
@@ -1089,11 +1165,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1089 | 1165 | ||
1090 | AppDomain sandbox; | 1166 | AppDomain sandbox; |
1091 | if (m_AppDomainLoading) | 1167 | if (m_AppDomainLoading) |
1168 | { | ||
1092 | sandbox = AppDomain.CreateDomain( | 1169 | sandbox = AppDomain.CreateDomain( |
1093 | m_Scene.RegionInfo.RegionID.ToString(), | 1170 | m_Scene.RegionInfo.RegionID.ToString(), |
1094 | evidence, appSetup); | 1171 | evidence, appSetup); |
1172 | m_AppDomains[appDomain].AssemblyResolve += | ||
1173 | new ResolveEventHandler( | ||
1174 | AssemblyResolver.OnAssemblyResolve); | ||
1175 | } | ||
1095 | else | 1176 | else |
1177 | { | ||
1096 | sandbox = AppDomain.CurrentDomain; | 1178 | sandbox = AppDomain.CurrentDomain; |
1179 | } | ||
1097 | 1180 | ||
1098 | //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); | 1181 | //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); |
1099 | //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); | 1182 | //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); |
@@ -1105,9 +1188,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1105 | 1188 | ||
1106 | m_AppDomains[appDomain] = sandbox; | 1189 | m_AppDomains[appDomain] = sandbox; |
1107 | 1190 | ||
1108 | m_AppDomains[appDomain].AssemblyResolve += | ||
1109 | new ResolveEventHandler( | ||
1110 | AssemblyResolver.OnAssemblyResolve); | ||
1111 | m_DomainScripts[appDomain] = new List<UUID>(); | 1191 | m_DomainScripts[appDomain] = new List<UUID>(); |
1112 | } | 1192 | } |
1113 | catch (Exception e) | 1193 | catch (Exception e) |
@@ -1392,25 +1472,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1392 | return false; | 1472 | return false; |
1393 | 1473 | ||
1394 | uuids = m_PrimObjects[localID]; | 1474 | uuids = m_PrimObjects[localID]; |
1395 | |||
1396 | 1475 | ||
1397 | foreach (UUID itemID in uuids) | 1476 | foreach (UUID itemID in uuids) |
1398 | { | ||
1399 | IScriptInstance instance = null; | ||
1400 | try | ||
1401 | { | ||
1402 | if (m_Scripts.ContainsKey(itemID)) | ||
1403 | instance = m_Scripts[itemID]; | ||
1404 | } | ||
1405 | catch { /* ignore race conditions */ } | ||
1406 | |||
1407 | if (instance != null) | ||
1408 | { | 1477 | { |
1409 | instance.PostEvent(p); | 1478 | IScriptInstance instance = null; |
1410 | result = true; | 1479 | try |
1480 | { | ||
1481 | if (m_Scripts.ContainsKey(itemID)) | ||
1482 | instance = m_Scripts[itemID]; | ||
1483 | } | ||
1484 | catch { /* ignore race conditions */ } | ||
1485 | |||
1486 | if (instance != null) | ||
1487 | { | ||
1488 | instance.PostEvent(p); | ||
1489 | result = true; | ||
1490 | } | ||
1411 | } | 1491 | } |
1412 | } | 1492 | } |
1413 | } | ||
1414 | 1493 | ||
1415 | return result; | 1494 | return result; |
1416 | } | 1495 | } |
@@ -1535,6 +1614,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1535 | } | 1614 | } |
1536 | } | 1615 | } |
1537 | 1616 | ||
1617 | public void SetRunEnable(UUID instanceID, bool enable) | ||
1618 | { | ||
1619 | IScriptInstance instance = GetInstance(instanceID); | ||
1620 | if (instance != null) | ||
1621 | instance.Run = enable; | ||
1622 | } | ||
1623 | |||
1538 | public bool GetScriptState(UUID itemID) | 1624 | public bool GetScriptState(UUID itemID) |
1539 | { | 1625 | { |
1540 | IScriptInstance instance = GetInstance(itemID); | 1626 | IScriptInstance instance = GetInstance(itemID); |
@@ -1745,14 +1831,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1745 | FileMode.Open, FileAccess.Read)) | 1831 | FileMode.Open, FileAccess.Read)) |
1746 | { | 1832 | { |
1747 | tfs.Read(tdata, 0, tdata.Length); | 1833 | tfs.Read(tdata, 0, tdata.Length); |
1748 | tfs.Close(); | ||
1749 | } | 1834 | } |
1750 | 1835 | ||
1751 | assem = new System.Text.ASCIIEncoding().GetString(tdata); | 1836 | assem = new System.Text.ASCIIEncoding().GetString(tdata); |
1752 | } | 1837 | } |
1753 | catch (Exception e) | 1838 | catch (Exception e) |
1754 | { | 1839 | { |
1755 | m_log.DebugFormat("[XEngine]: Unable to open script textfile {0}, reason: {1}", assemName+".text", e.Message); | 1840 | m_log.ErrorFormat( |
1841 | "[XEngine]: Unable to open script textfile {0}{1}, reason: {2}", | ||
1842 | assemName, ".text", e.Message); | ||
1756 | } | 1843 | } |
1757 | } | 1844 | } |
1758 | } | 1845 | } |
@@ -1769,16 +1856,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1769 | using (FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read)) | 1856 | using (FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read)) |
1770 | { | 1857 | { |
1771 | fs.Read(data, 0, data.Length); | 1858 | fs.Read(data, 0, data.Length); |
1772 | fs.Close(); | ||
1773 | } | 1859 | } |
1774 | 1860 | ||
1775 | assem = System.Convert.ToBase64String(data); | 1861 | assem = System.Convert.ToBase64String(data); |
1776 | } | 1862 | } |
1777 | catch (Exception e) | 1863 | catch (Exception e) |
1778 | { | 1864 | { |
1779 | m_log.DebugFormat("[XEngine]: Unable to open script assembly {0}, reason: {1}", assemName, e.Message); | 1865 | m_log.ErrorFormat( |
1866 | "[XEngine]: Unable to open script assembly {0}, reason: {1}", assemName, e.Message); | ||
1780 | } | 1867 | } |
1781 | |||
1782 | } | 1868 | } |
1783 | } | 1869 | } |
1784 | 1870 | ||
@@ -1791,9 +1877,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1791 | using (StreamReader msr = new StreamReader(mfs)) | 1877 | using (StreamReader msr = new StreamReader(mfs)) |
1792 | { | 1878 | { |
1793 | map = msr.ReadToEnd(); | 1879 | map = msr.ReadToEnd(); |
1794 | msr.Close(); | ||
1795 | } | 1880 | } |
1796 | mfs.Close(); | ||
1797 | } | 1881 | } |
1798 | } | 1882 | } |
1799 | 1883 | ||
@@ -1829,6 +1913,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1829 | 1913 | ||
1830 | public bool SetXMLState(UUID itemID, string xml) | 1914 | public bool SetXMLState(UUID itemID, string xml) |
1831 | { | 1915 | { |
1916 | // m_log.DebugFormat("[XEngine]: Writing state for script item with ID {0}", itemID); | ||
1917 | |||
1832 | if (xml == String.Empty) | 1918 | if (xml == String.Empty) |
1833 | return false; | 1919 | return false; |
1834 | 1920 | ||
@@ -1889,31 +1975,61 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1889 | { | 1975 | { |
1890 | using (FileStream fs = File.Create(path)) | 1976 | using (FileStream fs = File.Create(path)) |
1891 | { | 1977 | { |
1978 | // m_log.DebugFormat("[XEngine]: Writing assembly file {0}", path); | ||
1979 | |||
1892 | fs.Write(filedata, 0, filedata.Length); | 1980 | fs.Write(filedata, 0, filedata.Length); |
1893 | fs.Close(); | ||
1894 | } | 1981 | } |
1895 | } | 1982 | } |
1896 | catch (IOException ex) | 1983 | catch (IOException ex) |
1897 | { | 1984 | { |
1898 | // if there already exists a file at that location, it may be locked. | 1985 | // if there already exists a file at that location, it may be locked. |
1899 | m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", path, ex.Message); | 1986 | m_log.ErrorFormat("[XEngine]: Error whilst writing assembly file {0}, {1}", path, ex.Message); |
1900 | } | 1987 | } |
1988 | |||
1989 | string textpath = path + ".text"; | ||
1901 | try | 1990 | try |
1902 | { | 1991 | { |
1903 | using (FileStream fs = File.Create(path + ".text")) | 1992 | using (FileStream fs = File.Create(textpath)) |
1904 | { | 1993 | { |
1905 | using (StreamWriter sw = new StreamWriter(fs)) | 1994 | using (StreamWriter sw = new StreamWriter(fs)) |
1906 | { | 1995 | { |
1996 | // m_log.DebugFormat("[XEngine]: Writing .text file {0}", textpath); | ||
1997 | |||
1907 | sw.Write(base64); | 1998 | sw.Write(base64); |
1908 | sw.Close(); | ||
1909 | } | 1999 | } |
1910 | fs.Close(); | ||
1911 | } | 2000 | } |
1912 | } | 2001 | } |
1913 | catch (IOException ex) | 2002 | catch (IOException ex) |
1914 | { | 2003 | { |
1915 | // if there already exists a file at that location, it may be locked. | 2004 | // if there already exists a file at that location, it may be locked. |
1916 | m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", path, ex.Message); | 2005 | m_log.ErrorFormat("[XEngine]: Error whilst writing .text file {0}, {1}", textpath, ex.Message); |
2006 | } | ||
2007 | } | ||
2008 | |||
2009 | XmlNodeList mapL = rootE.GetElementsByTagName("LineMap"); | ||
2010 | if (mapL.Count > 0) | ||
2011 | { | ||
2012 | XmlElement mapE = (XmlElement)mapL[0]; | ||
2013 | |||
2014 | string mappath = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); | ||
2015 | mappath = Path.Combine(mappath, mapE.GetAttribute("Filename")); | ||
2016 | |||
2017 | try | ||
2018 | { | ||
2019 | using (FileStream mfs = File.Create(mappath)) | ||
2020 | { | ||
2021 | using (StreamWriter msw = new StreamWriter(mfs)) | ||
2022 | { | ||
2023 | // m_log.DebugFormat("[XEngine]: Writing linemap file {0}", mappath); | ||
2024 | |||
2025 | msw.Write(mapE.InnerText); | ||
2026 | } | ||
2027 | } | ||
2028 | } | ||
2029 | catch (IOException ex) | ||
2030 | { | ||
2031 | // if there already exists a file at that location, it may be locked. | ||
2032 | m_log.ErrorFormat("[XEngine]: Linemap file {0} already exists! {1}", mappath, ex.Message); | ||
1917 | } | 2033 | } |
1918 | } | 2034 | } |
1919 | } | 2035 | } |
@@ -1927,43 +2043,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1927 | { | 2043 | { |
1928 | using (StreamWriter ssw = new StreamWriter(sfs)) | 2044 | using (StreamWriter ssw = new StreamWriter(sfs)) |
1929 | { | 2045 | { |
2046 | // m_log.DebugFormat("[XEngine]: Writing state file {0}", statepath); | ||
2047 | |||
1930 | ssw.Write(stateE.OuterXml); | 2048 | ssw.Write(stateE.OuterXml); |
1931 | ssw.Close(); | ||
1932 | } | 2049 | } |
1933 | sfs.Close(); | ||
1934 | } | 2050 | } |
1935 | } | 2051 | } |
1936 | catch (IOException ex) | 2052 | catch (IOException ex) |
1937 | { | 2053 | { |
1938 | // if there already exists a file at that location, it may be locked. | 2054 | // if there already exists a file at that location, it may be locked. |
1939 | m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", statepath, ex.Message); | 2055 | m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message); |
1940 | } | ||
1941 | |||
1942 | XmlNodeList mapL = rootE.GetElementsByTagName("LineMap"); | ||
1943 | if (mapL.Count > 0) | ||
1944 | { | ||
1945 | XmlElement mapE = (XmlElement)mapL[0]; | ||
1946 | |||
1947 | string mappath = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); | ||
1948 | mappath = Path.Combine(mappath, mapE.GetAttribute("Filename")); | ||
1949 | |||
1950 | try | ||
1951 | { | ||
1952 | using (FileStream mfs = File.Create(mappath)) | ||
1953 | { | ||
1954 | using (StreamWriter msw = new StreamWriter(mfs)) | ||
1955 | { | ||
1956 | msw.Write(mapE.InnerText); | ||
1957 | msw.Close(); | ||
1958 | } | ||
1959 | mfs.Close(); | ||
1960 | } | ||
1961 | } | ||
1962 | catch (IOException ex) | ||
1963 | { | ||
1964 | // if there already exists a file at that location, it may be locked. | ||
1965 | m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", statepath, ex.Message); | ||
1966 | } | ||
1967 | } | 2056 | } |
1968 | 2057 | ||
1969 | return true; | 2058 | return true; |
@@ -1997,45 +2086,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1997 | if (!topScripts.ContainsKey(si.LocalID)) | 2086 | if (!topScripts.ContainsKey(si.LocalID)) |
1998 | topScripts[si.RootLocalID] = 0; | 2087 | topScripts[si.RootLocalID] = 0; |
1999 | 2088 | ||
2000 | // long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; | 2089 | topScripts[si.RootLocalID] += CalculateAdjustedExectionTime(si, tickNow); |
2001 | // float framesElapsed = ticksElapsed / (18.1818 * TimeSpan.TicksPerMillisecond); | 2090 | } |
2002 | 2091 | } | |
2003 | // Execution time of the script adjusted by it's measurement period to make scripts started at | ||
2004 | // different times comparable. | ||
2005 | // float adjustedExecutionTime | ||
2006 | // = (float)si.MeasurementPeriodExecutionTime | ||
2007 | // / ((float)(tickNow - si.MeasurementPeriodTickStart) / ScriptInstance.MaxMeasurementPeriod) | ||
2008 | // / TimeSpan.TicksPerMillisecond; | ||
2009 | |||
2010 | long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; | ||
2011 | |||
2012 | // Avoid divide by zerp | ||
2013 | if (ticksElapsed == 0) | ||
2014 | ticksElapsed = 1; | ||
2015 | 2092 | ||
2016 | // Scale execution time to the ideal 55 fps frame time for these reasons. | 2093 | return topScripts; |
2017 | // | 2094 | } |
2018 | // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no | ||
2019 | // 'script execution time per frame', which is the original purpose of this value. | ||
2020 | // | ||
2021 | // 2) Giving the raw execution times is misleading since scripts start at different times, making | ||
2022 | // it impossible to compare scripts. | ||
2023 | // | ||
2024 | // 3) Scaling the raw execution time to the time that the script has been running is better but | ||
2025 | // is still misleading since a script that has just been rezzed may appear to have been running | ||
2026 | // for much longer. | ||
2027 | // | ||
2028 | // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect | ||
2029 | // since the figure does not represent actual execution time and very hard running scripts will | ||
2030 | // never exceed 18ms (though this is a very high number for script execution so is a warning sign). | ||
2031 | float adjustedExecutionTime | ||
2032 | = ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f; | ||
2033 | 2095 | ||
2034 | topScripts[si.RootLocalID] += adjustedExecutionTime; | 2096 | public float GetScriptExecutionTime(List<UUID> itemIDs) |
2097 | { | ||
2098 | if (itemIDs == null|| itemIDs.Count == 0) | ||
2099 | { | ||
2100 | return 0.0f; | ||
2101 | } | ||
2102 | float time = 0.0f; | ||
2103 | long tickNow = Util.EnvironmentTickCount(); | ||
2104 | IScriptInstance si; | ||
2105 | // Calculate the time for all scripts that this engine is executing | ||
2106 | // Ignore any others | ||
2107 | foreach (UUID id in itemIDs) | ||
2108 | { | ||
2109 | si = GetInstance(id); | ||
2110 | if (si != null && si.Running) | ||
2111 | { | ||
2112 | time += CalculateAdjustedExectionTime(si, tickNow); | ||
2035 | } | 2113 | } |
2036 | } | 2114 | } |
2115 | return time; | ||
2116 | } | ||
2037 | 2117 | ||
2038 | return topScripts; | 2118 | private float CalculateAdjustedExectionTime(IScriptInstance si, long tickNow) |
2119 | { | ||
2120 | long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; | ||
2121 | |||
2122 | // Avoid divide by zero | ||
2123 | if (ticksElapsed == 0) | ||
2124 | ticksElapsed = 1; | ||
2125 | |||
2126 | // Scale execution time to the ideal 55 fps frame time for these reasons. | ||
2127 | // | ||
2128 | // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no | ||
2129 | // 'script execution time per frame', which is the original purpose of this value. | ||
2130 | // | ||
2131 | // 2) Giving the raw execution times is misleading since scripts start at different times, making | ||
2132 | // it impossible to compare scripts. | ||
2133 | // | ||
2134 | // 3) Scaling the raw execution time to the time that the script has been running is better but | ||
2135 | // is still misleading since a script that has just been rezzed may appear to have been running | ||
2136 | // for much longer. | ||
2137 | // | ||
2138 | // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect | ||
2139 | // since the figure does not represent actual execution time and very hard running scripts will | ||
2140 | // never exceed 18ms (though this is a very high number for script execution so is a warning sign). | ||
2141 | return ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f; | ||
2039 | } | 2142 | } |
2040 | 2143 | ||
2041 | public void SuspendScript(UUID itemID) | 2144 | public void SuspendScript(UUID itemID) |