diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine')
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs | 61 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/EventManager.cs | 10 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs | 7 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/Resources/XEngine.addin.xml | 13 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs (renamed from OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs) | 7 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs | 195 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs | 152 | ||||
-rwxr-xr-x[-rw-r--r--] | OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 609 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs | 10 |
9 files changed, 846 insertions, 218 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs new file mode 100644 index 0000000..f4211c8 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs | |||
@@ -0,0 +1,61 @@ | |||
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 OpenSimulator 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 | |||
28 | using System; | ||
29 | using System.Runtime.Remoting; | ||
30 | using System.Runtime.Remoting.Lifetime; | ||
31 | using System.Security.Permissions; | ||
32 | using System.Threading; | ||
33 | using System.Reflection; | ||
34 | using System.Collections; | ||
35 | using System.Collections.Generic; | ||
36 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
37 | using OpenSim.Region.ScriptEngine.Shared; | ||
38 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | ||
39 | |||
40 | namespace OpenSim.Region.ScriptEngine.XEngine.ScriptBase | ||
41 | { | ||
42 | public class XEngineScriptBase : ScriptBaseClass | ||
43 | { | ||
44 | /// <summary> | ||
45 | /// Used for script sleeps when we are using co-operative script termination. | ||
46 | /// </summary> | ||
47 | /// <remarks>null if co-operative script termination is not active</remarks> | ||
48 | WaitHandle m_coopSleepHandle; | ||
49 | |||
50 | public XEngineScriptBase(WaitHandle coopSleepHandle) : base() | ||
51 | { | ||
52 | m_coopSleepHandle = coopSleepHandle; | ||
53 | } | ||
54 | |||
55 | public void opensim_reserved_CheckForCoopTermination() | ||
56 | { | ||
57 | if (m_coopSleepHandle != null && m_coopSleepHandle.WaitOne(0)) | ||
58 | throw new ScriptCoopStopException(); | ||
59 | } | ||
60 | } | ||
61 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 9405075..0ff2da3 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs | |||
@@ -52,7 +52,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
52 | { | 52 | { |
53 | myScriptEngine = _ScriptEngine; | 53 | myScriptEngine = _ScriptEngine; |
54 | 54 | ||
55 | m_log.Info("[XEngine] Hooking up to server events"); | 55 | // m_log.Info("[XEngine] Hooking up to server events"); |
56 | myScriptEngine.World.EventManager.OnAttach += attach; | 56 | myScriptEngine.World.EventManager.OnAttach += attach; |
57 | myScriptEngine.World.EventManager.OnObjectGrab += touch_start; | 57 | myScriptEngine.World.EventManager.OnObjectGrab += touch_start; |
58 | myScriptEngine.World.EventManager.OnObjectGrabbing += touch; | 58 | myScriptEngine.World.EventManager.OnObjectGrabbing += touch; |
@@ -62,6 +62,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
62 | myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target; | 62 | myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target; |
63 | myScriptEngine.World.EventManager.OnScriptAtRotTargetEvent += at_rot_target; | 63 | myScriptEngine.World.EventManager.OnScriptAtRotTargetEvent += at_rot_target; |
64 | myScriptEngine.World.EventManager.OnScriptNotAtRotTargetEvent += not_at_rot_target; | 64 | myScriptEngine.World.EventManager.OnScriptNotAtRotTargetEvent += not_at_rot_target; |
65 | myScriptEngine.World.EventManager.OnScriptMovingStartEvent += moving_start; | ||
66 | myScriptEngine.World.EventManager.OnScriptMovingEndEvent += moving_end; | ||
65 | myScriptEngine.World.EventManager.OnScriptControlEvent += control; | 67 | myScriptEngine.World.EventManager.OnScriptControlEvent += control; |
66 | myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start; | 68 | myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start; |
67 | myScriptEngine.World.EventManager.OnScriptColliding += collision; | 69 | myScriptEngine.World.EventManager.OnScriptColliding += collision; |
@@ -69,7 +71,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
69 | myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start; | 71 | myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start; |
70 | myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision; | 72 | myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision; |
71 | myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end; | 73 | myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end; |
72 | IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>(); | 74 | IMoneyModule money = myScriptEngine.World.RequestModuleInterface<IMoneyModule>(); |
73 | if (money != null) | 75 | if (money != null) |
74 | { | 76 | { |
75 | money.OnObjectPaid+=HandleObjectPaid; | 77 | money.OnObjectPaid+=HandleObjectPaid; |
@@ -419,14 +421,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
419 | // dataserver: not handled here | 421 | // dataserver: not handled here |
420 | // link_message: not handled here | 422 | // link_message: not handled here |
421 | 423 | ||
422 | public void moving_start(uint localID, UUID itemID) | 424 | public void moving_start(uint localID) |
423 | { | 425 | { |
424 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 426 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
425 | "moving_start",new object[0], | 427 | "moving_start",new object[0], |
426 | new DetectParams[0])); | 428 | new DetectParams[0])); |
427 | } | 429 | } |
428 | 430 | ||
429 | public void moving_end(uint localID, UUID itemID) | 431 | public void moving_end(uint localID) |
430 | { | 432 | { |
431 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 433 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
432 | "moving_end",new object[0], | 434 | "moving_end",new object[0], |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs index bd26a8b..665929d 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs | |||
@@ -1,6 +1,7 @@ | |||
1 | using System.Reflection; | 1 | using System.Reflection; |
2 | using System.Runtime.CompilerServices; | 2 | using System.Runtime.CompilerServices; |
3 | using System.Runtime.InteropServices; | 3 | using System.Runtime.InteropServices; |
4 | using Mono.Addins; | ||
4 | 5 | ||
5 | // General Information about an assembly is controlled through the following | 6 | // General Information about an assembly is controlled through the following |
6 | // set of attributes. Change these attribute values to modify the information | 7 | // set of attributes. Change these attribute values to modify the information |
@@ -29,5 +30,7 @@ using System.Runtime.InteropServices; | |||
29 | // Build Number | 30 | // Build Number |
30 | // Revision | 31 | // Revision |
31 | // | 32 | // |
32 | [assembly: AssemblyVersion("0.7.5.*")] | 33 | [assembly: AssemblyVersion("0.8.3.*")] |
33 | [assembly: AssemblyFileVersion("1.0.0.0")] | 34 | |
35 | [assembly: Addin("OpenSim.Region.ScriptEngine.XEngine", OpenSim.VersionInfo.VersionNumber)] | ||
36 | [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] | ||
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Resources/XEngine.addin.xml b/OpenSim/Region/ScriptEngine/XEngine/Resources/XEngine.addin.xml deleted file mode 100644 index 96c9c3a..0000000 --- a/OpenSim/Region/ScriptEngine/XEngine/Resources/XEngine.addin.xml +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | <Addin id="OpenSim.Region.ScriptEngine.XEngine" version="0.2"> | ||
2 | <Runtime> | ||
3 | <Import assembly="OpenSim.Region.ScriptEngine.XEngine.dll"/> | ||
4 | </Runtime> | ||
5 | |||
6 | <Dependencies> | ||
7 | <Addin id="OpenSim" version="0.5" /> | ||
8 | </Dependencies> | ||
9 | |||
10 | <Extension path = "/OpenSim/RegionModules"> | ||
11 | <RegionModule id="XEngine" type="OpenSim.Region.ScriptEngine.XEngine.XEngine" /> | ||
12 | </Extension> | ||
13 | </Addin> | ||
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs index 5abfe9a..878e571 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs | |||
@@ -36,15 +36,14 @@ using OpenSim.Region.CoreModules.Scripting.WorldComm; | |||
36 | using OpenSim.Region.Framework.Scenes; | 36 | using OpenSim.Region.Framework.Scenes; |
37 | using OpenSim.Region.Framework.Interfaces; | 37 | using OpenSim.Region.Framework.Interfaces; |
38 | using OpenSim.Tests.Common; | 38 | using OpenSim.Tests.Common; |
39 | using OpenSim.Tests.Common.Mock; | ||
40 | 39 | ||
41 | namespace OpenSim.Region.ScriptEngine.XEngine.Tests | 40 | namespace OpenSim.Region.ScriptEngine.XEngine.Tests |
42 | { | 41 | { |
43 | /// <summary> | 42 | /// <summary> |
44 | /// XEngine tests. | 43 | /// Basic XEngine tests. |
45 | /// </summary> | 44 | /// </summary> |
46 | [TestFixture] | 45 | [TestFixture] |
47 | public class XEngineTest : OpenSimTestCase | 46 | public class XEngineBasicTests : OpenSimTestCase |
48 | { | 47 | { |
49 | private TestScene m_scene; | 48 | private TestScene m_scene; |
50 | private XEngine m_xEngine; | 49 | private XEngine m_xEngine; |
@@ -87,7 +86,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests | |||
87 | public void TestCompileAndStartScript() | 86 | public void TestCompileAndStartScript() |
88 | { | 87 | { |
89 | TestHelpers.InMethod(); | 88 | TestHelpers.InMethod(); |
90 | // log4net.Config.XmlConfigurator.Configure(); | 89 | TestHelpers.EnableLogging(); |
91 | 90 | ||
92 | UUID userId = TestHelpers.ParseTail(0x1); | 91 | UUID userId = TestHelpers.ParseTail(0x1); |
93 | // UUID objectId = TestHelpers.ParseTail(0x100); | 92 | // UUID objectId = TestHelpers.ParseTail(0x100); |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs new file mode 100644 index 0000000..587695f --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs | |||
@@ -0,0 +1,195 @@ | |||
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 OpenSimulator 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 | |||
28 | using System; | ||
29 | using System.Threading; | ||
30 | using Nini.Config; | ||
31 | using NUnit.Framework; | ||
32 | using OpenMetaverse; | ||
33 | using OpenSim.Framework; | ||
34 | using OpenSim.Region.CoreModules.Framework.EntityTransfer; | ||
35 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; | ||
36 | using OpenSim.Region.Framework.Scenes; | ||
37 | using OpenSim.Region.ScriptEngine.Shared; | ||
38 | using OpenSim.Tests.Common; | ||
39 | |||
40 | namespace OpenSim.Region.ScriptEngine.XEngine.Tests | ||
41 | { | ||
42 | /// <summary> | ||
43 | /// XEngine tests connected with crossing scripts between regions. | ||
44 | /// </summary> | ||
45 | [TestFixture] | ||
46 | public class XEngineCrossingTests : OpenSimTestCase | ||
47 | { | ||
48 | [TestFixtureSetUp] | ||
49 | public void FixtureInit() | ||
50 | { | ||
51 | // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. | ||
52 | Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; | ||
53 | } | ||
54 | |||
55 | [TestFixtureTearDown] | ||
56 | public void TearDown() | ||
57 | { | ||
58 | // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple | ||
59 | // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression | ||
60 | // tests really shouldn't). | ||
61 | Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; | ||
62 | } | ||
63 | |||
64 | /// <summary> | ||
65 | /// Test script state preservation when a script crosses between regions on the same simulator. | ||
66 | /// </summary> | ||
67 | [Test] | ||
68 | public void TestScriptCrossOnSameSimulator() | ||
69 | { | ||
70 | TestHelpers.InMethod(); | ||
71 | // TestHelpers.EnableLogging(); | ||
72 | |||
73 | UUID userId = TestHelpers.ParseTail(0x1); | ||
74 | int sceneObjectIdTail = 0x2; | ||
75 | |||
76 | EntityTransferModule etmA = new EntityTransferModule(); | ||
77 | EntityTransferModule etmB = new EntityTransferModule(); | ||
78 | LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); | ||
79 | XEngine xEngineA = new XEngine(); | ||
80 | XEngine xEngineB = new XEngine(); | ||
81 | xEngineA.DebugLevel = 1; | ||
82 | xEngineB.DebugLevel = 1; | ||
83 | |||
84 | IConfigSource configSource = new IniConfigSource(); | ||
85 | |||
86 | IConfig startupConfig = configSource.AddConfig("Startup"); | ||
87 | startupConfig.Set("DefaultScriptEngine", "XEngine"); | ||
88 | |||
89 | IConfig xEngineConfig = configSource.AddConfig("XEngine"); | ||
90 | xEngineConfig.Set("Enabled", "true"); | ||
91 | xEngineConfig.Set("StartDelay", "0"); | ||
92 | |||
93 | // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call | ||
94 | // to AssemblyResolver.OnAssemblyResolve fails. | ||
95 | xEngineConfig.Set("AppDomainLoading", "false"); | ||
96 | |||
97 | IConfig modulesConfig = configSource.AddConfig("Modules"); | ||
98 | modulesConfig.Set("EntityTransferModule", etmA.Name); | ||
99 | modulesConfig.Set("SimulationServices", lscm.Name); | ||
100 | |||
101 | SceneHelpers sh = new SceneHelpers(); | ||
102 | TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000, configSource); | ||
103 | TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999, configSource); | ||
104 | |||
105 | SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, configSource, lscm); | ||
106 | SceneHelpers.SetupSceneModules(sceneA, configSource, etmA, xEngineA); | ||
107 | SceneHelpers.SetupSceneModules(sceneB, configSource, etmB, xEngineB); | ||
108 | sceneA.StartScripts(); | ||
109 | sceneB.StartScripts(); | ||
110 | |||
111 | SceneObjectGroup soSceneA = SceneHelpers.AddSceneObject(sceneA, 1, userId, "so1-", sceneObjectIdTail); | ||
112 | soSceneA.AbsolutePosition = new Vector3(128, 10, 20); | ||
113 | |||
114 | // CREATE SCRIPT TODO | ||
115 | InventoryItemBase scriptItemSceneA = new InventoryItemBase(); | ||
116 | // itemTemplate.ID = itemId; | ||
117 | scriptItemSceneA.Name = "script1"; | ||
118 | scriptItemSceneA.Folder = soSceneA.UUID; | ||
119 | scriptItemSceneA.InvType = (int)InventoryType.LSL; | ||
120 | |||
121 | AutoResetEvent chatEvent = new AutoResetEvent(false); | ||
122 | OSChatMessage messageReceived = null; | ||
123 | sceneA.EventManager.OnChatFromWorld += (s, m) => { messageReceived = m; chatEvent.Set(); }; | ||
124 | |||
125 | sceneA.RezNewScript(userId, scriptItemSceneA, | ||
126 | @"integer c = 0; | ||
127 | |||
128 | default | ||
129 | { | ||
130 | state_entry() | ||
131 | { | ||
132 | llSay(0, ""Script running""); | ||
133 | } | ||
134 | |||
135 | changed(integer change) | ||
136 | { | ||
137 | llSay(0, ""Changed""); | ||
138 | } | ||
139 | |||
140 | touch_start(integer n) | ||
141 | { | ||
142 | c = c + 1; | ||
143 | llSay(0, (string)c); | ||
144 | } | ||
145 | }"); | ||
146 | |||
147 | chatEvent.WaitOne(60000); | ||
148 | |||
149 | Assert.That(messageReceived, Is.Not.Null, "No chat message received."); | ||
150 | Assert.That(messageReceived.Message, Is.EqualTo("Script running")); | ||
151 | |||
152 | { | ||
153 | // XXX: Should not be doing this so directly. Should call some variant of EventManager.touch() instead. | ||
154 | DetectParams[] det = new DetectParams[1]; | ||
155 | det[0] = new DetectParams(); | ||
156 | det[0].Key = userId; | ||
157 | det[0].Populate(sceneA); | ||
158 | |||
159 | EventParams ep = new EventParams("touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, det); | ||
160 | |||
161 | xEngineA.PostObjectEvent(soSceneA.LocalId, ep); | ||
162 | chatEvent.WaitOne(60000); | ||
163 | |||
164 | Assert.That(messageReceived.Message, Is.EqualTo("1")); | ||
165 | } | ||
166 | |||
167 | sceneB.EventManager.OnChatFromWorld += (s, m) => { messageReceived = m; chatEvent.Set(); }; | ||
168 | |||
169 | // Cross with a negative value | ||
170 | soSceneA.AbsolutePosition = new Vector3(128, -10, 20); | ||
171 | |||
172 | chatEvent.WaitOne(60000); | ||
173 | Assert.That(messageReceived.Message, Is.EqualTo("Changed")); | ||
174 | |||
175 | // TEST sending event to moved prim and output | ||
176 | { | ||
177 | SceneObjectGroup soSceneB = sceneB.GetSceneObjectGroup(soSceneA.Name); | ||
178 | TaskInventoryItem scriptItemSceneB = soSceneB.RootPart.Inventory.GetInventoryItem(scriptItemSceneA.Name); | ||
179 | |||
180 | // XXX: Should not be doing this so directly. Should call some variant of EventManager.touch() instead. | ||
181 | DetectParams[] det = new DetectParams[1]; | ||
182 | det[0] = new DetectParams(); | ||
183 | det[0].Key = userId; | ||
184 | det[0].Populate(sceneB); | ||
185 | |||
186 | EventParams ep = new EventParams("touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, det); | ||
187 | |||
188 | xEngineB.PostObjectEvent(soSceneB.LocalId, ep); | ||
189 | chatEvent.WaitOne(60000); | ||
190 | |||
191 | Assert.That(messageReceived.Message, Is.EqualTo("2")); | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs new file mode 100644 index 0000000..2ef4058 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs | |||
@@ -0,0 +1,152 @@ | |||
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 OpenSimulator 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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.Linq; | ||
32 | using System.Threading; | ||
33 | using Nini.Config; | ||
34 | using NUnit.Framework; | ||
35 | using OpenMetaverse; | ||
36 | using OpenSim.Framework; | ||
37 | using OpenSim.Region.CoreModules.Avatar.Attachments; | ||
38 | using OpenSim.Region.CoreModules.Framework.InventoryAccess; | ||
39 | using OpenSim.Region.Framework.Scenes; | ||
40 | using OpenSim.Region.ScriptEngine.XEngine; | ||
41 | using OpenSim.Services.Interfaces; | ||
42 | using OpenSim.Tests.Common; | ||
43 | |||
44 | namespace OpenSim.Region.ScriptEngine.Tests | ||
45 | { | ||
46 | [TestFixture] | ||
47 | public class XEnginePersistenceTests : OpenSimTestCase | ||
48 | { | ||
49 | private AutoResetEvent m_chatEvent = new AutoResetEvent(false); | ||
50 | |||
51 | private void OnChatFromWorld(object sender, OSChatMessage oscm) | ||
52 | { | ||
53 | // Console.WriteLine("Got chat [{0}]", oscm.Message); | ||
54 | |||
55 | // m_osChatMessageReceived = oscm; | ||
56 | m_chatEvent.Set(); | ||
57 | } | ||
58 | |||
59 | private void AddCommonConfig(IConfigSource config, List<object> modules) | ||
60 | { | ||
61 | config.AddConfig("Modules"); | ||
62 | config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); | ||
63 | |||
64 | AttachmentsModule attMod = new AttachmentsModule(); | ||
65 | attMod.DebugLevel = 1; | ||
66 | modules.Add(attMod); | ||
67 | modules.Add(new BasicInventoryAccessModule()); | ||
68 | } | ||
69 | |||
70 | private void AddScriptingConfig(IConfigSource config, XEngine.XEngine xEngine, List<object> modules) | ||
71 | { | ||
72 | IConfig startupConfig = config.AddConfig("Startup"); | ||
73 | startupConfig.Set("DefaultScriptEngine", "XEngine"); | ||
74 | |||
75 | IConfig xEngineConfig = config.AddConfig("XEngine"); | ||
76 | xEngineConfig.Set("Enabled", "true"); | ||
77 | xEngineConfig.Set("StartDelay", "0"); | ||
78 | |||
79 | // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call | ||
80 | // to AssemblyResolver.OnAssemblyResolve fails. | ||
81 | xEngineConfig.Set("AppDomainLoading", "false"); | ||
82 | |||
83 | modules.Add(xEngine); | ||
84 | } | ||
85 | |||
86 | private Scene CreateScriptingEnabledTestScene(XEngine.XEngine xEngine) | ||
87 | { | ||
88 | IConfigSource config = new IniConfigSource(); | ||
89 | List<object> modules = new List<object>(); | ||
90 | |||
91 | AddCommonConfig(config, modules); | ||
92 | AddScriptingConfig(config, xEngine, modules); | ||
93 | |||
94 | Scene scene | ||
95 | = new SceneHelpers().SetupScene( | ||
96 | "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); | ||
97 | SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); | ||
98 | |||
99 | scene.StartScripts(); | ||
100 | |||
101 | return scene; | ||
102 | } | ||
103 | |||
104 | [Test] | ||
105 | public void TestScriptedAttachmentPersistence() | ||
106 | { | ||
107 | TestHelpers.InMethod(); | ||
108 | // TestHelpers.EnableLogging(); | ||
109 | |||
110 | XEngine.XEngine xEngine = new XEngine.XEngine(); | ||
111 | Scene scene = CreateScriptingEnabledTestScene(xEngine); | ||
112 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); | ||
113 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); | ||
114 | |||
115 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); | ||
116 | TaskInventoryHelpers.AddScript( | ||
117 | scene.AssetService, | ||
118 | so.RootPart, | ||
119 | "scriptItem", | ||
120 | "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }"); | ||
121 | |||
122 | InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); | ||
123 | |||
124 | // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. | ||
125 | // In the future, we need to be able to do this programatically more predicably. | ||
126 | scene.EventManager.OnChatFromWorld += OnChatFromWorld; | ||
127 | |||
128 | SceneObjectGroup rezzedSo | ||
129 | = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); | ||
130 | TaskInventoryItem rezzedScriptItem = rezzedSo.RootPart.Inventory.GetInventoryItem("scriptItem"); | ||
131 | |||
132 | // Wait for chat to signal rezzed script has been started. | ||
133 | m_chatEvent.WaitOne(60000); | ||
134 | |||
135 | // Force save | ||
136 | xEngine.DoBackup(new Object[] { 0 }); | ||
137 | |||
138 | // Console.WriteLine("ItemID {0}", rezzedScriptItem.ItemID); | ||
139 | // | ||
140 | // foreach ( | ||
141 | // string s in Directory.EnumerateFileSystemEntries( | ||
142 | // string.Format("ScriptEngines/{0}", scene.RegionInfo.RegionID))) | ||
143 | // Console.WriteLine(s); | ||
144 | |||
145 | Assert.IsFalse( | ||
146 | File.Exists( | ||
147 | string.Format("ScriptEngines/{0}/{1}.state", scene.RegionInfo.RegionID, rezzedScriptItem.ItemID))); | ||
148 | |||
149 | scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo); | ||
150 | } | ||
151 | } | ||
152 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 18569ca..78d4ee9 100644..100755 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -42,22 +42,26 @@ using OpenMetaverse.StructuredData; | |||
42 | using log4net; | 42 | using log4net; |
43 | using Nini.Config; | 43 | using Nini.Config; |
44 | using Amib.Threading; | 44 | using Amib.Threading; |
45 | using Mono.Addins; | ||
45 | using OpenSim.Framework; | 46 | using OpenSim.Framework; |
46 | using OpenSim.Framework.Console; | 47 | using OpenSim.Framework.Console; |
47 | using OpenSim.Region.Framework.Scenes; | 48 | using OpenSim.Region.Framework.Scenes; |
48 | using OpenSim.Region.Framework.Interfaces; | 49 | using OpenSim.Region.Framework.Interfaces; |
50 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
49 | using OpenSim.Region.ScriptEngine.Shared; | 51 | using OpenSim.Region.ScriptEngine.Shared; |
50 | using OpenSim.Region.ScriptEngine.Shared.CodeTools; | 52 | using OpenSim.Region.ScriptEngine.Shared.CodeTools; |
51 | using OpenSim.Region.ScriptEngine.Shared.Instance; | 53 | using OpenSim.Region.ScriptEngine.Shared.Instance; |
52 | using OpenSim.Region.ScriptEngine.Shared.Api; | 54 | using OpenSim.Region.ScriptEngine.Shared.Api; |
53 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; | 55 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; |
54 | using OpenSim.Region.ScriptEngine.Interfaces; | 56 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; |
57 | using OpenSim.Region.ScriptEngine.XEngine.ScriptBase; | ||
55 | using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; | 58 | using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; |
56 | 59 | ||
57 | using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; | 60 | using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; |
58 | 61 | ||
59 | namespace OpenSim.Region.ScriptEngine.XEngine | 62 | namespace OpenSim.Region.ScriptEngine.XEngine |
60 | { | 63 | { |
64 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEngine")] | ||
61 | public class XEngine : INonSharedRegionModule, IScriptModule, IScriptEngine | 65 | public class XEngine : INonSharedRegionModule, IScriptModule, IScriptEngine |
62 | { | 66 | { |
63 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 67 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
@@ -68,7 +72,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
68 | /// <remarks> | 72 | /// <remarks> |
69 | /// If DebugLevel >= 1, then we log every time that a script is started. | 73 | /// If DebugLevel >= 1, then we log every time that a script is started. |
70 | /// </remarks> | 74 | /// </remarks> |
71 | // public int DebugLevel { get; set; } | 75 | public int DebugLevel { get; set; } |
76 | |||
77 | /// <summary> | ||
78 | /// A parameter to allow us to notify the log if at least one script has a compilation that is not compatible | ||
79 | /// with ScriptStopStrategy. | ||
80 | /// </summary> | ||
81 | public bool HaveNotifiedLogOfScriptStopMistmatch { get; private set; } | ||
72 | 82 | ||
73 | private SmartThreadPool m_ThreadPool; | 83 | private SmartThreadPool m_ThreadPool; |
74 | private int m_MaxScriptQueue; | 84 | private int m_MaxScriptQueue; |
@@ -84,6 +94,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
84 | /// </summary> | 94 | /// </summary> |
85 | private int m_StartDelay; | 95 | private int m_StartDelay; |
86 | 96 | ||
97 | /// <summary> | ||
98 | /// Are we stopping scripts co-operatively by inserting checks in them at C# compile time (true) or aborting | ||
99 | /// their threads (false)? | ||
100 | /// </summary> | ||
101 | private bool m_coopTermination; | ||
102 | |||
87 | private int m_IdleTimeout; | 103 | private int m_IdleTimeout; |
88 | private int m_StackSize; | 104 | private int m_StackSize; |
89 | private int m_SleepTime; | 105 | private int m_SleepTime; |
@@ -93,7 +109,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
93 | private bool m_InitialStartup = true; | 109 | private bool m_InitialStartup = true; |
94 | private int m_ScriptFailCount; // Number of script fails since compile queue was last empty | 110 | private int m_ScriptFailCount; // Number of script fails since compile queue was last empty |
95 | private string m_ScriptErrorMessage; | 111 | private string m_ScriptErrorMessage; |
96 | private Dictionary<string, string> m_uniqueScripts = new Dictionary<string, string>(); | ||
97 | private bool m_AppDomainLoading; | 112 | private bool m_AppDomainLoading; |
98 | private Dictionary<UUID,ArrayList> m_ScriptErrors = | 113 | private Dictionary<UUID,ArrayList> m_ScriptErrors = |
99 | new Dictionary<UUID,ArrayList>(); | 114 | new Dictionary<UUID,ArrayList>(); |
@@ -175,6 +190,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
175 | get { return "XEngine"; } | 190 | get { return "XEngine"; } |
176 | } | 191 | } |
177 | 192 | ||
193 | public string ScriptClassName { get; private set; } | ||
194 | |||
195 | public string ScriptBaseClassName { get; private set; } | ||
196 | |||
197 | public ParameterInfo[] ScriptBaseClassParameters { get; private set; } | ||
198 | |||
199 | public string[] ScriptReferencedAssemblies { get; private set; } | ||
200 | |||
178 | public Scene World | 201 | public Scene World |
179 | { | 202 | { |
180 | get { return m_Scene; } | 203 | get { return m_Scene; } |
@@ -229,21 +252,36 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
229 | 252 | ||
230 | m_ScriptConfig = configSource.Configs["XEngine"]; | 253 | m_ScriptConfig = configSource.Configs["XEngine"]; |
231 | m_ConfigSource = configSource; | 254 | m_ConfigSource = configSource; |
255 | |||
256 | string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "co-op"); | ||
257 | |||
258 | m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy); | ||
259 | |||
260 | if (rawScriptStopStrategy == "co-op") | ||
261 | { | ||
262 | m_coopTermination = true; | ||
263 | ScriptClassName = "XEngineScript"; | ||
264 | ScriptBaseClassName = typeof(XEngineScriptBase).FullName; | ||
265 | ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters(); | ||
266 | ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) }; | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | ScriptClassName = "Script"; | ||
271 | ScriptBaseClassName = typeof(ScriptBaseClass).FullName; | ||
272 | } | ||
273 | |||
274 | // Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]); | ||
232 | } | 275 | } |
233 | 276 | ||
234 | public void AddRegion(Scene scene) | 277 | public void AddRegion(Scene scene) |
235 | { | 278 | { |
236 | if (m_ScriptConfig == null) | 279 | if (m_ScriptConfig == null) |
237 | return; | 280 | return; |
281 | |||
238 | m_ScriptFailCount = 0; | 282 | m_ScriptFailCount = 0; |
239 | m_ScriptErrorMessage = String.Empty; | 283 | m_ScriptErrorMessage = String.Empty; |
240 | 284 | ||
241 | if (m_ScriptConfig == null) | ||
242 | { | ||
243 | // m_log.ErrorFormat("[XEngine] No script configuration found. Scripts disabled"); | ||
244 | return; | ||
245 | } | ||
246 | |||
247 | m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true); | 285 | m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true); |
248 | 286 | ||
249 | if (!m_Enabled) | 287 | if (!m_Enabled) |
@@ -365,19 +403,19 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
365 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); | 403 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); |
366 | 404 | ||
367 | MainConsole.Instance.Commands.AddCommand( | 405 | MainConsole.Instance.Commands.AddCommand( |
368 | "Scripts", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script", | 406 | "Debug", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a particular script.", |
369 | "Activates or deactivates extra debug logging for the given script.\n" | 407 | "Activates or deactivates extra debug logging for the given script.\n" |
370 | + "Level == 0, deactivate extra debug logging.\n" | 408 | + "Level == 0, deactivate extra debug logging.\n" |
371 | + "Level >= 1, log state changes.\n" | 409 | + "Level >= 1, log state changes.\n" |
372 | + "Level >= 2, log event invocations.\n", | 410 | + "Level >= 2, log event invocations.\n", |
373 | HandleDebugScriptLogCommand); | 411 | HandleDebugScriptLogCommand); |
374 | 412 | ||
375 | // MainConsole.Instance.Commands.AddCommand( | 413 | MainConsole.Instance.Commands.AddCommand( |
376 | // "Debug", false, "debug xengine", "debug xengine [<level>]", | 414 | "Debug", false, "debug xengine log", "debug xengine log [<level>]", |
377 | // "Turn on detailed xengine debugging.", | 415 | "Turn on detailed xengine debugging.", |
378 | // "If level <= 0, then no extra logging is done.\n" | 416 | "If level <= 0, then no extra logging is done.\n" |
379 | // + "If level >= 1, then we log every time that a script is started.", | 417 | + "If level >= 1, then we log every time that a script is started.", |
380 | // HandleDebugLevelCommand); | 418 | HandleDebugLevelCommand); |
381 | } | 419 | } |
382 | 420 | ||
383 | private void HandleDebugScriptLogCommand(string module, string[] args) | 421 | private void HandleDebugScriptLogCommand(string module, string[] args) |
@@ -420,26 +458,26 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
420 | /// </summary> | 458 | /// </summary> |
421 | /// <param name="module"></param> | 459 | /// <param name="module"></param> |
422 | /// <param name="args"></param> | 460 | /// <param name="args"></param> |
423 | // private void HandleDebugLevelCommand(string module, string[] args) | 461 | private void HandleDebugLevelCommand(string module, string[] args) |
424 | // { | 462 | { |
425 | // if (args.Length == 3) | 463 | if (args.Length >= 4) |
426 | // { | 464 | { |
427 | // int newDebug; | 465 | int newDebug; |
428 | // if (int.TryParse(args[2], out newDebug)) | 466 | if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, args[3], out newDebug)) |
429 | // { | 467 | { |
430 | // DebugLevel = newDebug; | 468 | DebugLevel = newDebug; |
431 | // MainConsole.Instance.OutputFormat("Debug level set to {0}", newDebug); | 469 | MainConsole.Instance.OutputFormat("Debug level set to {0} in XEngine for region {1}", newDebug, m_Scene.Name); |
432 | // } | 470 | } |
433 | // } | 471 | } |
434 | // else if (args.Length == 2) | 472 | else if (args.Length == 3) |
435 | // { | 473 | { |
436 | // MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel); | 474 | MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel); |
437 | // } | 475 | } |
438 | // else | 476 | else |
439 | // { | 477 | { |
440 | // MainConsole.Instance.Output("Usage: debug xengine 0..1"); | 478 | MainConsole.Instance.Output("Usage: debug xengine log <level>"); |
441 | // } | 479 | } |
442 | // } | 480 | } |
443 | 481 | ||
444 | /// <summary> | 482 | /// <summary> |
445 | /// Parse the raw item id into a script instance from the command params if it's present. | 483 | /// Parse the raw item id into a script instance from the command params if it's present. |
@@ -459,7 +497,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
459 | /// <param name="instance"></param> | 497 | /// <param name="instance"></param> |
460 | /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param> | 498 | /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param> |
461 | private void HandleScriptsAction<TKey>( | 499 | private void HandleScriptsAction<TKey>( |
462 | string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector) | 500 | string[] cmdparams, Action<IScriptInstance> action, System.Func<IScriptInstance, TKey> keySelector) |
463 | { | 501 | { |
464 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) | 502 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) |
465 | return; | 503 | return; |
@@ -517,7 +555,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
517 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) | 555 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) |
518 | return; | 556 | return; |
519 | 557 | ||
520 | MainConsole.Instance.OutputFormat(GetStatusReport()); | 558 | MainConsole.Instance.Output(GetStatusReport()); |
521 | } | 559 | } |
522 | 560 | ||
523 | public string GetStatusReport() | 561 | public string GetStatusReport() |
@@ -539,7 +577,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
539 | } | 577 | } |
540 | 578 | ||
541 | sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded); | 579 | sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded); |
542 | sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); | ||
543 | sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); | 580 | sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); |
544 | sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); | 581 | sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); |
545 | sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads); | 582 | sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads); |
@@ -616,7 +653,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
616 | sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); | 653 | sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); |
617 | sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); | 654 | sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); |
618 | 655 | ||
619 | MainConsole.Instance.OutputFormat(sb.ToString()); | 656 | MainConsole.Instance.Output(sb.ToString()); |
620 | } | 657 | } |
621 | 658 | ||
622 | private void HandleSuspendScript(IScriptInstance instance) | 659 | private void HandleSuspendScript(IScriptInstance instance) |
@@ -662,6 +699,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
662 | { | 699 | { |
663 | if (instance.Running) | 700 | if (instance.Running) |
664 | { | 701 | { |
702 | instance.StayStopped = true; // the script was stopped explicitly | ||
703 | |||
665 | instance.Stop(0); | 704 | instance.Stop(0); |
666 | 705 | ||
667 | SceneObjectPart sop = m_Scene.GetSceneObjectPart(instance.ObjectID); | 706 | SceneObjectPart sop = m_Scene.GetSceneObjectPart(instance.ObjectID); |
@@ -685,28 +724,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
685 | { | 724 | { |
686 | // Force a final state save | 725 | // Force a final state save |
687 | // | 726 | // |
688 | if (m_Assemblies.ContainsKey(instance.AssetID)) | 727 | try |
689 | { | 728 | { |
690 | string assembly = m_Assemblies[instance.AssetID]; | 729 | if (instance.StatePersistedHere) |
691 | 730 | instance.SaveState(); | |
692 | try | 731 | } |
693 | { | 732 | catch (Exception e) |
694 | instance.SaveState(assembly); | 733 | { |
695 | } | 734 | m_log.Error( |
696 | catch (Exception e) | 735 | string.Format( |
697 | { | 736 | "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", |
698 | m_log.Error( | 737 | instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name) |
699 | string.Format( | 738 | , e); |
700 | "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", | ||
701 | instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name) | ||
702 | , e); | ||
703 | } | ||
704 | } | 739 | } |
705 | 740 | ||
706 | // Clear the event queue and abort the instance thread | 741 | // Clear the event queue and abort the instance thread |
707 | // | 742 | // |
708 | instance.ClearQueue(); | 743 | instance.Stop(0, true); |
709 | instance.Stop(0); | ||
710 | 744 | ||
711 | // Release events, timer, etc | 745 | // Release events, timer, etc |
712 | // | 746 | // |
@@ -804,23 +838,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
804 | lock (m_Scripts) | 838 | lock (m_Scripts) |
805 | { | 839 | { |
806 | foreach (IScriptInstance instance in m_Scripts.Values) | 840 | foreach (IScriptInstance instance in m_Scripts.Values) |
807 | instances.Add(instance); | 841 | { |
842 | if (instance.StatePersistedHere) | ||
843 | { | ||
844 | // m_log.DebugFormat( | ||
845 | // "[XEngine]: Adding script {0}.{1}, item UUID {2}, prim UUID {3} in {4} for state persistence", | ||
846 | // instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name); | ||
847 | |||
848 | instances.Add(instance); | ||
849 | } | ||
850 | } | ||
808 | } | 851 | } |
809 | 852 | ||
810 | foreach (IScriptInstance i in instances) | 853 | foreach (IScriptInstance i in instances) |
811 | { | 854 | { |
812 | string assembly = String.Empty; | ||
813 | |||
814 | lock (m_Scripts) | ||
815 | { | ||
816 | if (!m_Assemblies.ContainsKey(i.AssetID)) | ||
817 | continue; | ||
818 | assembly = m_Assemblies[i.AssetID]; | ||
819 | } | ||
820 | |||
821 | try | 855 | try |
822 | { | 856 | { |
823 | i.SaveState(assembly); | 857 | i.SaveState(); |
824 | } | 858 | } |
825 | catch (Exception e) | 859 | catch (Exception e) |
826 | { | 860 | { |
@@ -832,8 +866,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
832 | } | 866 | } |
833 | } | 867 | } |
834 | 868 | ||
835 | instances.Clear(); | ||
836 | |||
837 | if (saveTime > 0) | 869 | if (saveTime > 0) |
838 | m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), | 870 | m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), |
839 | new Object[] { saveTime }); | 871 | new Object[] { saveTime }); |
@@ -843,6 +875,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
843 | 875 | ||
844 | public void SaveAllState() | 876 | public void SaveAllState() |
845 | { | 877 | { |
878 | DoBackup(new object[] { 0 }); | ||
879 | } | ||
880 | |||
881 | public object DoMaintenance(object p) | ||
882 | { | ||
883 | object[] parms = (object[])p; | ||
884 | int sleepTime = (int)parms[0]; | ||
885 | |||
846 | foreach (IScriptInstance inst in m_Scripts.Values) | 886 | foreach (IScriptInstance inst in m_Scripts.Values) |
847 | { | 887 | { |
848 | if (inst.EventTime() > m_EventLimit) | 888 | if (inst.EventTime() > m_EventLimit) |
@@ -852,14 +892,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
852 | inst.Start(); | 892 | inst.Start(); |
853 | } | 893 | } |
854 | } | 894 | } |
855 | } | ||
856 | |||
857 | public object DoMaintenance(object p) | ||
858 | { | ||
859 | object[] parms = (object[])p; | ||
860 | int sleepTime = (int)parms[0]; | ||
861 | |||
862 | SaveAllState(); | ||
863 | 895 | ||
864 | System.Threading.Thread.Sleep(sleepTime); | 896 | System.Threading.Thread.Sleep(sleepTime); |
865 | 897 | ||
@@ -937,8 +969,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
937 | if (restOfFirstLine.StartsWith("c#") | 969 | if (restOfFirstLine.StartsWith("c#") |
938 | || restOfFirstLine.StartsWith("vb") | 970 | || restOfFirstLine.StartsWith("vb") |
939 | || restOfFirstLine.StartsWith("lsl") | 971 | || restOfFirstLine.StartsWith("lsl") |
940 | || restOfFirstLine.StartsWith("js") | ||
941 | || restOfFirstLine.StartsWith("yp") | ||
942 | || restOfFirstLine.Length == 0) | 972 | || restOfFirstLine.Length == 0) |
943 | warnRunningInXEngine = true; | 973 | warnRunningInXEngine = true; |
944 | 974 | ||
@@ -972,12 +1002,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
972 | if (engine != ScriptEngineName) | 1002 | if (engine != ScriptEngineName) |
973 | return; | 1003 | return; |
974 | 1004 | ||
975 | // If we've seen this exact script text before, use that reference instead | ||
976 | if (m_uniqueScripts.ContainsKey(script)) | ||
977 | script = m_uniqueScripts[script]; | ||
978 | else | ||
979 | m_uniqueScripts[script] = script; | ||
980 | |||
981 | Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource}; | 1005 | Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource}; |
982 | 1006 | ||
983 | if (stateSource == (int)StateSource.ScriptedRez) | 1007 | if (stateSource == (int)StateSource.ScriptedRez) |
@@ -991,11 +1015,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
991 | } | 1015 | } |
992 | else | 1016 | else |
993 | { | 1017 | { |
994 | m_CompileQueue.Enqueue(parms); | ||
995 | lock (m_CompileDict) | 1018 | lock (m_CompileDict) |
996 | { | ||
997 | m_CompileDict[itemID] = 0; | 1019 | m_CompileDict[itemID] = 0; |
998 | } | 1020 | |
1021 | // This must occur after the m_CompileDict so that an existing compile thread cannot hit the check | ||
1022 | // in DoOnRezScript() before m_CompileDict has been updated. | ||
1023 | m_CompileQueue.Enqueue(parms); | ||
999 | 1024 | ||
1000 | // m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID); | 1025 | // m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID); |
1001 | 1026 | ||
@@ -1017,49 +1042,81 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1017 | 1042 | ||
1018 | public Object DoOnRezScriptQueue(Object dummy) | 1043 | public Object DoOnRezScriptQueue(Object dummy) |
1019 | { | 1044 | { |
1020 | if (m_InitialStartup) | 1045 | try |
1021 | { | 1046 | { |
1022 | // This delay exists to stop mono problems where script compilation and startup would stop the sim | 1047 | if (m_InitialStartup) |
1023 | // working properly for the session. | 1048 | { |
1024 | System.Threading.Thread.Sleep(m_StartDelay); | 1049 | // This delay exists to stop mono problems where script compilation and startup would stop the sim |
1050 | // working properly for the session. | ||
1051 | System.Threading.Thread.Sleep(m_StartDelay); | ||
1025 | 1052 | ||
1026 | m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name); | 1053 | m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name); |
1027 | } | 1054 | } |
1028 | 1055 | ||
1029 | object[] o; | 1056 | object[] o; |
1030 | 1057 | ||
1031 | int scriptsStarted = 0; | 1058 | int scriptsStarted = 0; |
1032 | 1059 | ||
1033 | while (m_CompileQueue.Dequeue(out o)) | 1060 | while (m_CompileQueue.Dequeue(out o)) |
1034 | { | ||
1035 | if (DoOnRezScript(o)) | ||
1036 | { | 1061 | { |
1037 | scriptsStarted++; | 1062 | try |
1063 | { | ||
1064 | if (DoOnRezScript(o)) | ||
1065 | { | ||
1066 | scriptsStarted++; | ||
1038 | 1067 | ||
1039 | if (m_InitialStartup) | 1068 | if (m_InitialStartup) |
1040 | if (scriptsStarted % 50 == 0) | 1069 | if (scriptsStarted % 50 == 0) |
1041 | m_log.InfoFormat( | 1070 | m_log.InfoFormat( |
1042 | "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); | 1071 | "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); |
1072 | } | ||
1073 | } | ||
1074 | catch (Exception e) | ||
1075 | { | ||
1076 | m_log.Error( | ||
1077 | string.Format( | ||
1078 | "[XEngine]: Failure in DoOnRezScriptQueue() for item {0} in {1}. Continuing. Exception ", | ||
1079 | o[1], m_Scene.Name), | ||
1080 | e); | ||
1081 | } | ||
1043 | } | 1082 | } |
1044 | } | ||
1045 | 1083 | ||
1046 | if (m_InitialStartup) | 1084 | if (m_InitialStartup) |
1047 | m_log.InfoFormat( | 1085 | m_log.InfoFormat( |
1048 | "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name); | 1086 | "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name); |
1049 | 1087 | ||
1050 | // NOTE: Despite having a lockless queue, this lock is required | 1088 | } |
1051 | // to make sure there is never no compile thread while there | 1089 | catch (Exception e) |
1052 | // are still scripts to compile. This could otherwise happen | 1090 | { |
1053 | // due to a race condition | 1091 | m_log.Error( |
1054 | // | 1092 | string.Format("[XEngine]: Failure in DoOnRezScriptQueue() in {0}. Exception ", m_Scene.Name), e); |
1055 | lock (m_CompileQueue) | 1093 | } |
1056 | m_CurrentCompile = null; | 1094 | finally |
1095 | { | ||
1096 | // FIXME: On failure we must trigger this even if the compile queue is not actually empty so that the | ||
1097 | // RegionReadyModule is not forever waiting. This event really needs a different name. | ||
1098 | m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount, | ||
1099 | m_ScriptErrorMessage); | ||
1057 | 1100 | ||
1058 | m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount, | 1101 | m_ScriptFailCount = 0; |
1059 | m_ScriptErrorMessage); | 1102 | m_InitialStartup = false; |
1060 | 1103 | ||
1061 | m_ScriptFailCount = 0; | 1104 | // NOTE: Despite having a lockless queue, this lock is required |
1062 | m_InitialStartup = false; | 1105 | // to make sure there is never no compile thread while there |
1106 | // are still scripts to compile. This could otherwise happen | ||
1107 | // due to a race condition | ||
1108 | // | ||
1109 | lock (m_CompileQueue) | ||
1110 | { | ||
1111 | m_CurrentCompile = null; | ||
1112 | |||
1113 | // This is to avoid a situation where the m_CompileQueue while loop above could complete but | ||
1114 | // OnRezScript() place a new script on the queue and check m_CurrentCompile = null before we hit | ||
1115 | // this section. | ||
1116 | if (m_CompileQueue.Count > 0) | ||
1117 | m_CurrentCompile = m_ThreadPool.QueueWorkItem(DoOnRezScriptQueue, null); | ||
1118 | } | ||
1119 | } | ||
1063 | 1120 | ||
1064 | return null; | 1121 | return null; |
1065 | } | 1122 | } |
@@ -1106,16 +1163,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1106 | return false; | 1163 | return false; |
1107 | } | 1164 | } |
1108 | 1165 | ||
1109 | m_log.DebugFormat( | 1166 | if (DebugLevel > 0) |
1110 | "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", | 1167 | m_log.DebugFormat( |
1111 | part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, | 1168 | "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", |
1112 | part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); | 1169 | part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, |
1170 | part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); | ||
1113 | 1171 | ||
1114 | UUID assetID = item.AssetID; | 1172 | UUID assetID = item.AssetID; |
1115 | 1173 | ||
1116 | ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); | 1174 | ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); |
1117 | 1175 | ||
1118 | string assembly = ""; | 1176 | string assemblyPath = ""; |
1119 | 1177 | ||
1120 | Culture.SetCurrentCulture(); | 1178 | Culture.SetCurrentCulture(); |
1121 | 1179 | ||
@@ -1127,11 +1185,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1127 | { | 1185 | { |
1128 | lock (m_AddingAssemblies) | 1186 | lock (m_AddingAssemblies) |
1129 | { | 1187 | { |
1130 | m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap); | 1188 | m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assemblyPath, out linemap); |
1131 | if (!m_AddingAssemblies.ContainsKey(assembly)) { | 1189 | |
1132 | m_AddingAssemblies[assembly] = 1; | 1190 | // m_log.DebugFormat( |
1191 | // "[XENGINE]: Found assembly path {0} onrez {1} in {2}", | ||
1192 | // assemblyPath, item.ItemID, World.Name); | ||
1193 | |||
1194 | if (!m_AddingAssemblies.ContainsKey(assemblyPath)) { | ||
1195 | m_AddingAssemblies[assemblyPath] = 1; | ||
1133 | } else { | 1196 | } else { |
1134 | m_AddingAssemblies[assembly]++; | 1197 | m_AddingAssemblies[assemblyPath]++; |
1135 | } | 1198 | } |
1136 | } | 1199 | } |
1137 | 1200 | ||
@@ -1177,7 +1240,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1177 | } | 1240 | } |
1178 | catch (Exception e) | 1241 | catch (Exception e) |
1179 | { | 1242 | { |
1180 | // m_log.ErrorFormat("[XEngine]: Exception when rezzing script {0}{1}", e.Message, e.StackTrace); | 1243 | // m_log.ErrorFormat( |
1244 | // "[XEngine]: Exception when rezzing script with item ID {0}, {1}{2}", | ||
1245 | // itemID, e.Message, e.StackTrace); | ||
1181 | 1246 | ||
1182 | // try | 1247 | // try |
1183 | // { | 1248 | // { |
@@ -1274,19 +1339,144 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1274 | m_ScriptFailCount++; | 1339 | m_ScriptFailCount++; |
1275 | lock (m_AddingAssemblies) | 1340 | lock (m_AddingAssemblies) |
1276 | { | 1341 | { |
1277 | m_AddingAssemblies[assembly]--; | 1342 | m_AddingAssemblies[assemblyPath]--; |
1278 | } | 1343 | } |
1279 | return false; | 1344 | return false; |
1280 | } | 1345 | } |
1281 | } | 1346 | } |
1282 | m_DomainScripts[appDomain].Add(itemID); | 1347 | m_DomainScripts[appDomain].Add(itemID); |
1283 | 1348 | ||
1349 | IScript scriptObj = null; | ||
1350 | EventWaitHandle coopSleepHandle; | ||
1351 | bool coopTerminationForThisScript; | ||
1352 | |||
1353 | // Set up assembly name to point to the appropriate scriptEngines directory | ||
1354 | AssemblyName assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(assemblyPath)); | ||
1355 | assemblyName.CodeBase = Path.GetDirectoryName(assemblyPath); | ||
1356 | |||
1357 | if (m_coopTermination) | ||
1358 | { | ||
1359 | try | ||
1360 | { | ||
1361 | coopSleepHandle = new XEngineEventWaitHandle(false, EventResetMode.AutoReset); | ||
1362 | |||
1363 | scriptObj | ||
1364 | = (IScript)m_AppDomains[appDomain].CreateInstanceAndUnwrap( | ||
1365 | assemblyName.FullName, | ||
1366 | "SecondLife.XEngineScript", | ||
1367 | false, | ||
1368 | BindingFlags.Default, | ||
1369 | null, | ||
1370 | new object[] { coopSleepHandle }, | ||
1371 | null, | ||
1372 | null); | ||
1373 | |||
1374 | coopTerminationForThisScript = true; | ||
1375 | } | ||
1376 | catch (TypeLoadException) | ||
1377 | { | ||
1378 | coopSleepHandle = null; | ||
1379 | |||
1380 | try | ||
1381 | { | ||
1382 | scriptObj | ||
1383 | = (IScript)m_AppDomains[appDomain].CreateInstanceAndUnwrap( | ||
1384 | assemblyName.FullName, | ||
1385 | "SecondLife.Script", | ||
1386 | false, | ||
1387 | BindingFlags.Default, | ||
1388 | null, | ||
1389 | null, | ||
1390 | null, | ||
1391 | null); | ||
1392 | } | ||
1393 | catch (Exception e2) | ||
1394 | { | ||
1395 | m_log.Error( | ||
1396 | string.Format( | ||
1397 | "[XENGINE]: Could not load previous SecondLife.Script from assembly {0} in {1}. Not starting. Exception ", | ||
1398 | assemblyName.FullName, World.Name), | ||
1399 | e2); | ||
1400 | |||
1401 | return false; | ||
1402 | } | ||
1403 | |||
1404 | coopTerminationForThisScript = false; | ||
1405 | } | ||
1406 | } | ||
1407 | else | ||
1408 | { | ||
1409 | try | ||
1410 | { | ||
1411 | scriptObj | ||
1412 | = (IScript)m_AppDomains[appDomain].CreateInstanceAndUnwrap( | ||
1413 | assemblyName.FullName, | ||
1414 | "SecondLife.Script", | ||
1415 | false, | ||
1416 | BindingFlags.Default, | ||
1417 | null, | ||
1418 | null, | ||
1419 | null, | ||
1420 | null); | ||
1421 | |||
1422 | coopSleepHandle = null; | ||
1423 | coopTerminationForThisScript = false; | ||
1424 | } | ||
1425 | catch (TypeLoadException) | ||
1426 | { | ||
1427 | coopSleepHandle = new XEngineEventWaitHandle(false, EventResetMode.AutoReset); | ||
1428 | |||
1429 | try | ||
1430 | { | ||
1431 | scriptObj | ||
1432 | = (IScript)m_AppDomains[appDomain].CreateInstanceAndUnwrap( | ||
1433 | assemblyName.FullName, | ||
1434 | "SecondLife.XEngineScript", | ||
1435 | false, | ||
1436 | BindingFlags.Default, | ||
1437 | null, | ||
1438 | new object[] { coopSleepHandle }, | ||
1439 | null, | ||
1440 | null); | ||
1441 | } | ||
1442 | catch (Exception e2) | ||
1443 | { | ||
1444 | m_log.Error( | ||
1445 | string.Format( | ||
1446 | "[XENGINE]: Could not load previous SecondLife.XEngineScript from assembly {0} in {1}. Not starting. Exception ", | ||
1447 | assemblyName.FullName, World.Name), | ||
1448 | e2); | ||
1449 | |||
1450 | return false; | ||
1451 | } | ||
1452 | |||
1453 | coopTerminationForThisScript = true; | ||
1454 | } | ||
1455 | } | ||
1456 | |||
1457 | if (m_coopTermination != coopTerminationForThisScript && !HaveNotifiedLogOfScriptStopMistmatch) | ||
1458 | { | ||
1459 | // Notify the log that there is at least one script compile that doesn't match the | ||
1460 | // ScriptStopStrategy. Operator has to manually delete old DLLs - we can't do this on Windows | ||
1461 | // once the assembly has been loaded evne if the instantiation of a class was unsuccessful. | ||
1462 | m_log.WarnFormat( | ||
1463 | "[XEngine]: At least one existing compiled script DLL in {0} has {1} as ScriptStopStrategy whereas config setting is {2}." | ||
1464 | + "\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).", | ||
1465 | World.Name, coopTerminationForThisScript ? "co-op" : "abort", m_coopTermination ? "co-op" : "abort"); | ||
1466 | |||
1467 | HaveNotifiedLogOfScriptStopMistmatch = true; | ||
1468 | } | ||
1469 | |||
1284 | instance = new ScriptInstance(this, part, | 1470 | instance = new ScriptInstance(this, part, |
1285 | itemID, assetID, assembly, | 1471 | item, |
1286 | m_AppDomains[appDomain], | 1472 | startParam, postOnRez, |
1287 | part.ParentGroup.RootPart.Name, | 1473 | m_MaxScriptQueue); |
1288 | item.Name, startParam, postOnRez, | 1474 | |
1289 | stateSource, m_MaxScriptQueue); | 1475 | if ( |
1476 | !instance.Load( | ||
1477 | scriptObj, coopSleepHandle, assemblyPath, | ||
1478 | Path.Combine(ScriptEnginePath, World.RegionInfo.RegionID.ToString()), stateSource, coopTerminationForThisScript)) | ||
1479 | return false; | ||
1290 | 1480 | ||
1291 | // if (DebugLevel >= 1) | 1481 | // if (DebugLevel >= 1) |
1292 | // m_log.DebugFormat( | 1482 | // m_log.DebugFormat( |
@@ -1317,11 +1507,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1317 | } | 1507 | } |
1318 | 1508 | ||
1319 | if (!m_Assemblies.ContainsKey(assetID)) | 1509 | if (!m_Assemblies.ContainsKey(assetID)) |
1320 | m_Assemblies[assetID] = assembly; | 1510 | m_Assemblies[assetID] = assemblyPath; |
1321 | 1511 | ||
1322 | lock (m_AddingAssemblies) | 1512 | lock (m_AddingAssemblies) |
1323 | { | 1513 | { |
1324 | m_AddingAssemblies[assembly]--; | 1514 | m_AddingAssemblies[assemblyPath]--; |
1325 | } | 1515 | } |
1326 | 1516 | ||
1327 | if (instance != null) | 1517 | if (instance != null) |
@@ -1359,11 +1549,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1359 | m_Scripts.Remove(itemID); | 1549 | m_Scripts.Remove(itemID); |
1360 | } | 1550 | } |
1361 | 1551 | ||
1362 | instance.ClearQueue(); | 1552 | instance.Stop(m_WaitForEventCompletionOnScriptStop, true); |
1363 | |||
1364 | instance.Stop(m_WaitForEventCompletionOnScriptStop); | ||
1365 | |||
1366 | // bool objectRemoved = false; | ||
1367 | 1553 | ||
1368 | lock (m_PrimObjects) | 1554 | lock (m_PrimObjects) |
1369 | { | 1555 | { |
@@ -1376,14 +1562,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1376 | 1562 | ||
1377 | // If there are no more scripts, remove prim | 1563 | // If there are no more scripts, remove prim |
1378 | if (m_PrimObjects[localID].Count == 0) | 1564 | if (m_PrimObjects[localID].Count == 0) |
1379 | { | ||
1380 | m_PrimObjects.Remove(localID); | 1565 | m_PrimObjects.Remove(localID); |
1381 | // objectRemoved = true; | ||
1382 | } | ||
1383 | } | 1566 | } |
1384 | } | 1567 | } |
1385 | 1568 | ||
1386 | instance.RemoveState(); | 1569 | if (instance.StatePersistedHere) |
1570 | instance.RemoveState(); | ||
1571 | |||
1387 | instance.DestroyScriptInstance(); | 1572 | instance.DestroyScriptInstance(); |
1388 | 1573 | ||
1389 | m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); | 1574 | m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); |
@@ -1489,7 +1674,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1489 | startInfo.MaxWorkerThreads = maxThreads; | 1674 | startInfo.MaxWorkerThreads = maxThreads; |
1490 | startInfo.MinWorkerThreads = minThreads; | 1675 | startInfo.MinWorkerThreads = minThreads; |
1491 | startInfo.ThreadPriority = threadPriority;; | 1676 | startInfo.ThreadPriority = threadPriority;; |
1492 | startInfo.StackSize = stackSize; | 1677 | startInfo.MaxStackSize = stackSize; |
1493 | startInfo.StartSuspended = true; | 1678 | startInfo.StartSuspended = true; |
1494 | 1679 | ||
1495 | m_ThreadPool = new SmartThreadPool(startInfo); | 1680 | m_ThreadPool = new SmartThreadPool(startInfo); |
@@ -1516,7 +1701,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1516 | 1701 | ||
1517 | IScriptInstance instance = (ScriptInstance) parms; | 1702 | IScriptInstance instance = (ScriptInstance) parms; |
1518 | 1703 | ||
1519 | //m_log.DebugFormat("[XEngine]: Processing event for {0}", instance); | 1704 | // m_log.DebugFormat("[XEngine]: Processing event for {0}", instance); |
1520 | 1705 | ||
1521 | return instance.EventProcessor(); | 1706 | return instance.EventProcessor(); |
1522 | } | 1707 | } |
@@ -1681,9 +1866,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1681 | public bool GetScriptState(UUID itemID) | 1866 | public bool GetScriptState(UUID itemID) |
1682 | { | 1867 | { |
1683 | IScriptInstance instance = GetInstance(itemID); | 1868 | IScriptInstance instance = GetInstance(itemID); |
1684 | if (instance != null) | 1869 | return instance != null && instance.Running; |
1685 | return instance.Running; | ||
1686 | return false; | ||
1687 | } | 1870 | } |
1688 | 1871 | ||
1689 | public void ApiResetScript(UUID itemID) | 1872 | public void ApiResetScript(UUID itemID) |
@@ -1691,6 +1874,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1691 | IScriptInstance instance = GetInstance(itemID); | 1874 | IScriptInstance instance = GetInstance(itemID); |
1692 | if (instance != null) | 1875 | if (instance != null) |
1693 | instance.ApiResetScript(); | 1876 | instance.ApiResetScript(); |
1877 | |||
1878 | // Send the new number of threads that are in use by the thread | ||
1879 | // pool, I believe that by adding them to the locations where the | ||
1880 | // script is changing states that I will catch all changes to the | ||
1881 | // thread pool | ||
1882 | m_Scene.setThreadCount(m_ThreadPool.InUseThreads); | ||
1694 | } | 1883 | } |
1695 | 1884 | ||
1696 | public void ResetScript(UUID itemID) | 1885 | public void ResetScript(UUID itemID) |
@@ -1698,6 +1887,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1698 | IScriptInstance instance = GetInstance(itemID); | 1887 | IScriptInstance instance = GetInstance(itemID); |
1699 | if (instance != null) | 1888 | if (instance != null) |
1700 | instance.ResetScript(m_WaitForEventCompletionOnScriptStop); | 1889 | instance.ResetScript(m_WaitForEventCompletionOnScriptStop); |
1890 | |||
1891 | // Send the new number of threads that are in use by the thread | ||
1892 | // pool, I believe that by adding them to the locations where the | ||
1893 | // script is changing states that I will catch all changes to the | ||
1894 | // thread pool | ||
1895 | m_Scene.setThreadCount(m_ThreadPool.InUseThreads); | ||
1701 | } | 1896 | } |
1702 | 1897 | ||
1703 | public void StartScript(UUID itemID) | 1898 | public void StartScript(UUID itemID) |
@@ -1707,6 +1902,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1707 | instance.Start(); | 1902 | instance.Start(); |
1708 | else | 1903 | else |
1709 | m_runFlags.AddOrUpdate(itemID, true, 240); | 1904 | m_runFlags.AddOrUpdate(itemID, true, 240); |
1905 | |||
1906 | // Send the new number of threads that are in use by the thread | ||
1907 | // pool, I believe that by adding them to the locations where the | ||
1908 | // script is changing states that I will catch all changes to the | ||
1909 | // thread pool | ||
1910 | m_Scene.setThreadCount(m_ThreadPool.InUseThreads); | ||
1710 | } | 1911 | } |
1711 | 1912 | ||
1712 | public void StopScript(UUID itemID) | 1913 | public void StopScript(UUID itemID) |
@@ -1714,17 +1915,29 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1714 | IScriptInstance instance = GetInstance(itemID); | 1915 | IScriptInstance instance = GetInstance(itemID); |
1715 | 1916 | ||
1716 | if (instance != null) | 1917 | if (instance != null) |
1918 | { | ||
1919 | lock (instance.EventQueue) | ||
1920 | instance.StayStopped = true; // the script was stopped explicitly | ||
1921 | |||
1717 | instance.Stop(m_WaitForEventCompletionOnScriptStop); | 1922 | instance.Stop(m_WaitForEventCompletionOnScriptStop); |
1923 | } | ||
1718 | else | 1924 | else |
1925 | { | ||
1926 | // m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name); | ||
1719 | m_runFlags.AddOrUpdate(itemID, false, 240); | 1927 | m_runFlags.AddOrUpdate(itemID, false, 240); |
1928 | } | ||
1929 | |||
1930 | // Send the new number of threads that are in use by the thread | ||
1931 | // pool, I believe that by adding them to the locations where the | ||
1932 | // script is changing states that I will catch all changes to the | ||
1933 | // thread pool | ||
1934 | m_Scene.setThreadCount(m_ThreadPool.InUseThreads); | ||
1720 | } | 1935 | } |
1721 | 1936 | ||
1722 | public DetectParams GetDetectParams(UUID itemID, int idx) | 1937 | public DetectParams GetDetectParams(UUID itemID, int idx) |
1723 | { | 1938 | { |
1724 | IScriptInstance instance = GetInstance(itemID); | 1939 | IScriptInstance instance = GetInstance(itemID); |
1725 | if (instance != null) | 1940 | return instance != null ? instance.GetDetectParams(idx) : null; |
1726 | return instance.GetDetectParams(idx); | ||
1727 | return null; | ||
1728 | } | 1941 | } |
1729 | 1942 | ||
1730 | public void SetMinEventDelay(UUID itemID, double delay) | 1943 | public void SetMinEventDelay(UUID itemID, double delay) |
@@ -1737,9 +1950,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1737 | public UUID GetDetectID(UUID itemID, int idx) | 1950 | public UUID GetDetectID(UUID itemID, int idx) |
1738 | { | 1951 | { |
1739 | IScriptInstance instance = GetInstance(itemID); | 1952 | IScriptInstance instance = GetInstance(itemID); |
1740 | if (instance != null) | 1953 | return instance != null ? instance.GetDetectID(idx) : UUID.Zero; |
1741 | return instance.GetDetectID(idx); | ||
1742 | return UUID.Zero; | ||
1743 | } | 1954 | } |
1744 | 1955 | ||
1745 | public void SetState(UUID itemID, string newState) | 1956 | public void SetState(UUID itemID, string newState) |
@@ -1753,9 +1964,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1753 | public int GetStartParameter(UUID itemID) | 1964 | public int GetStartParameter(UUID itemID) |
1754 | { | 1965 | { |
1755 | IScriptInstance instance = GetInstance(itemID); | 1966 | IScriptInstance instance = GetInstance(itemID); |
1756 | if (instance == null) | 1967 | return instance == null ? 0 : instance.StartParam; |
1757 | return 0; | ||
1758 | return instance.StartParam; | ||
1759 | } | 1968 | } |
1760 | 1969 | ||
1761 | public void OnShutdown() | 1970 | public void OnShutdown() |
@@ -1789,9 +1998,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1789 | public IScriptApi GetApi(UUID itemID, string name) | 1998 | public IScriptApi GetApi(UUID itemID, string name) |
1790 | { | 1999 | { |
1791 | IScriptInstance instance = GetInstance(itemID); | 2000 | IScriptInstance instance = GetInstance(itemID); |
1792 | if (instance == null) | 2001 | return instance == null ? null : instance.GetApi(name); |
1793 | return null; | ||
1794 | return instance.GetApi(name); | ||
1795 | } | 2002 | } |
1796 | 2003 | ||
1797 | public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) | 2004 | public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) |
@@ -2090,7 +2297,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2090 | catch (IOException ex) | 2297 | catch (IOException ex) |
2091 | { | 2298 | { |
2092 | // if there already exists a file at that location, it may be locked. | 2299 | // if there already exists a file at that location, it may be locked. |
2093 | m_log.ErrorFormat("[XEngine]: Linemap file {0} already exists! {1}", mappath, ex.Message); | 2300 | m_log.Error( |
2301 | string.Format("[XEngine]: Linemap file {0} could not be written. Exception ", mappath), ex); | ||
2094 | } | 2302 | } |
2095 | } | 2303 | } |
2096 | } | 2304 | } |
@@ -2116,6 +2324,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2116 | m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message); | 2324 | m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message); |
2117 | } | 2325 | } |
2118 | 2326 | ||
2327 | // m_log.DebugFormat( | ||
2328 | // "[XEngine]: Wrote state for script item with ID {0} at {1} in {2}", itemID, statepath, m_Scene.Name); | ||
2329 | |||
2119 | return true; | 2330 | return true; |
2120 | } | 2331 | } |
2121 | 2332 | ||
@@ -2137,7 +2348,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2137 | 2348 | ||
2138 | public Dictionary<uint, float> GetObjectScriptsExecutionTimes() | 2349 | public Dictionary<uint, float> GetObjectScriptsExecutionTimes() |
2139 | { | 2350 | { |
2140 | long tickNow = Util.EnvironmentTickCount(); | ||
2141 | Dictionary<uint, float> topScripts = new Dictionary<uint, float>(); | 2351 | Dictionary<uint, float> topScripts = new Dictionary<uint, float>(); |
2142 | 2352 | ||
2143 | lock (m_Scripts) | 2353 | lock (m_Scripts) |
@@ -2147,7 +2357,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2147 | if (!topScripts.ContainsKey(si.LocalID)) | 2357 | if (!topScripts.ContainsKey(si.LocalID)) |
2148 | topScripts[si.RootLocalID] = 0; | 2358 | topScripts[si.RootLocalID] = 0; |
2149 | 2359 | ||
2150 | topScripts[si.RootLocalID] += CalculateAdjustedExectionTime(si, tickNow); | 2360 | topScripts[si.RootLocalID] += GetExectionTime(si); |
2151 | } | 2361 | } |
2152 | } | 2362 | } |
2153 | 2363 | ||
@@ -2161,7 +2371,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2161 | return 0.0f; | 2371 | return 0.0f; |
2162 | } | 2372 | } |
2163 | float time = 0.0f; | 2373 | float time = 0.0f; |
2164 | long tickNow = Util.EnvironmentTickCount(); | ||
2165 | IScriptInstance si; | 2374 | IScriptInstance si; |
2166 | // Calculate the time for all scripts that this engine is executing | 2375 | // Calculate the time for all scripts that this engine is executing |
2167 | // Ignore any others | 2376 | // Ignore any others |
@@ -2170,36 +2379,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2170 | si = GetInstance(id); | 2379 | si = GetInstance(id); |
2171 | if (si != null && si.Running) | 2380 | if (si != null && si.Running) |
2172 | { | 2381 | { |
2173 | time += CalculateAdjustedExectionTime(si, tickNow); | 2382 | time += GetExectionTime(si); |
2174 | } | 2383 | } |
2175 | } | 2384 | } |
2176 | return time; | 2385 | return time; |
2177 | } | 2386 | } |
2178 | 2387 | ||
2179 | private float CalculateAdjustedExectionTime(IScriptInstance si, long tickNow) | 2388 | private float GetExectionTime(IScriptInstance si) |
2180 | { | 2389 | { |
2181 | long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; | 2390 | return (float)si.ExecutionTime.GetSumTime().TotalMilliseconds; |
2182 | |||
2183 | // Avoid divide by zero | ||
2184 | if (ticksElapsed == 0) | ||
2185 | ticksElapsed = 1; | ||
2186 | |||
2187 | // Scale execution time to the ideal 55 fps frame time for these reasons. | ||
2188 | // | ||
2189 | // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no | ||
2190 | // 'script execution time per frame', which is the original purpose of this value. | ||
2191 | // | ||
2192 | // 2) Giving the raw execution times is misleading since scripts start at different times, making | ||
2193 | // it impossible to compare scripts. | ||
2194 | // | ||
2195 | // 3) Scaling the raw execution time to the time that the script has been running is better but | ||
2196 | // is still misleading since a script that has just been rezzed may appear to have been running | ||
2197 | // for much longer. | ||
2198 | // | ||
2199 | // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect | ||
2200 | // since the figure does not represent actual execution time and very hard running scripts will | ||
2201 | // never exceed 18ms (though this is a very high number for script execution so is a warning sign). | ||
2202 | return ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f; | ||
2203 | } | 2391 | } |
2204 | 2392 | ||
2205 | public void SuspendScript(UUID itemID) | 2393 | public void SuspendScript(UUID itemID) |
@@ -2211,6 +2399,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2211 | instance.Suspend(); | 2399 | instance.Suspend(); |
2212 | // else | 2400 | // else |
2213 | // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); | 2401 | // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); |
2402 | |||
2403 | // Send the new number of threads that are in use by the thread | ||
2404 | // pool, I believe that by adding them to the locations where the | ||
2405 | // script is changing states that I will catch all changes to the | ||
2406 | // thread pool | ||
2407 | m_Scene.setThreadCount(m_ThreadPool.InUseThreads); | ||
2214 | } | 2408 | } |
2215 | 2409 | ||
2216 | public void ResumeScript(UUID itemID) | 2410 | public void ResumeScript(UUID itemID) |
@@ -2222,6 +2416,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2222 | instance.Resume(); | 2416 | instance.Resume(); |
2223 | // else | 2417 | // else |
2224 | // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); | 2418 | // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); |
2419 | |||
2420 | // Send the new number of threads that are in use by the thread | ||
2421 | // pool, I believe that by adding them to the locations where the | ||
2422 | // script is changing states that I will catch all changes to the | ||
2423 | // thread pool | ||
2424 | m_Scene.setThreadCount(m_ThreadPool.InUseThreads); | ||
2225 | } | 2425 | } |
2226 | 2426 | ||
2227 | public bool HasScript(UUID itemID, out bool running) | 2427 | public bool HasScript(UUID itemID, out bool running) |
@@ -2235,5 +2435,30 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
2235 | running = instance.Running; | 2435 | running = instance.Running; |
2236 | return true; | 2436 | return true; |
2237 | } | 2437 | } |
2438 | |||
2439 | public void SleepScript(UUID itemID, int delay) | ||
2440 | { | ||
2441 | IScriptInstance instance = GetInstance(itemID); | ||
2442 | if (instance == null) | ||
2443 | return; | ||
2444 | |||
2445 | instance.ExecutionTimer.Stop(); | ||
2446 | try | ||
2447 | { | ||
2448 | if (instance.CoopWaitHandle != null) | ||
2449 | { | ||
2450 | if (instance.CoopWaitHandle.WaitOne(delay)) | ||
2451 | throw new ScriptCoopStopException(); | ||
2452 | } | ||
2453 | else | ||
2454 | { | ||
2455 | Thread.Sleep(delay); | ||
2456 | } | ||
2457 | } | ||
2458 | finally | ||
2459 | { | ||
2460 | instance.ExecutionTimer.Start(); | ||
2461 | } | ||
2462 | } | ||
2238 | } | 2463 | } |
2239 | } | 2464 | } |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs index 2ac5c31..9d9dee1 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs | |||
@@ -52,13 +52,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
52 | return wr.Cancel(); | 52 | return wr.Cancel(); |
53 | } | 53 | } |
54 | 54 | ||
55 | public void Abort() | 55 | public bool Abort() |
56 | { | 56 | { |
57 | wr.Abort(); | 57 | return wr.Cancel(true); |
58 | } | 58 | } |
59 | 59 | ||
60 | public bool Wait(TimeSpan t) | 60 | public bool Wait(int t) |
61 | { | 61 | { |
62 | // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the | ||
63 | // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an | ||
64 | // int (32-bit) we can end up with bad values. This occurs on Windows though curiously not on Mono 2.10.8 | ||
65 | // (or very likely other versions of Mono at least up until 3.0.3). | ||
62 | return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); | 66 | return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); |
63 | } | 67 | } |
64 | } | 68 | } |