aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs49
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs73
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs195
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs148
6 files changed, 339 insertions, 132 deletions
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index b9a217b..1097efb 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -222,7 +222,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
222 void SetVars(Dictionary<string, object> vars); 222 void SetVars(Dictionary<string, object> vars);
223 DetectParams GetDetectParams(int idx); 223 DetectParams GetDetectParams(int idx);
224 UUID GetDetectID(int idx); 224 UUID GetDetectID(int idx);
225 void SaveState(string assembly); 225 void SaveState();
226 void DestroyScriptInstance(); 226 void DestroyScriptInstance();
227 227
228 IScriptApi GetApi(string name); 228 IScriptApi GetApi(string name);
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 9379f8f..de5f92d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -663,9 +663,8 @@ namespace SecondLife
663 663
664 try 664 try
665 { 665 {
666 FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read); 666 using (FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read))
667 fs.Read(data, 0, data.Length); 667 fs.Read(data, 0, data.Length);
668 fs.Close();
669 } 668 }
670 catch (Exception) 669 catch (Exception)
671 { 670 {
@@ -680,9 +679,8 @@ namespace SecondLife
680 679
681 Byte[] buf = Encoding.ASCII.GetBytes(filetext); 680 Byte[] buf = Encoding.ASCII.GetBytes(filetext);
682 681
683 FileStream sfs = File.Create(assembly + ".text"); 682 using (FileStream sfs = File.Create(assembly + ".text"))
684 sfs.Write(buf, 0, buf.Length); 683 sfs.Write(buf, 0, buf.Length);
685 sfs.Close();
686 684
687 return assembly; 685 return assembly;
688 } 686 }
@@ -775,7 +773,6 @@ namespace SecondLife
775 return message; 773 return message;
776 } 774 }
777 775
778
779 private static void WriteMapFile(string filename, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap) 776 private static void WriteMapFile(string filename, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap)
780 { 777 {
781 string mapstring = String.Empty; 778 string mapstring = String.Empty;
@@ -787,40 +784,42 @@ namespace SecondLife
787 } 784 }
788 785
789 Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring); 786 Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring);
790 FileStream mfs = File.Create(filename);
791 mfs.Write(mapbytes, 0, mapbytes.Length);
792 mfs.Close();
793 }
794 787
788 using (FileStream mfs = File.Create(filename))
789 mfs.Write(mapbytes, 0, mapbytes.Length);
790 }
795 791
796 private static Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> ReadMapFile(string filename) 792 private static Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> ReadMapFile(string filename)
797 { 793 {
798 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; 794 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
799 try 795 try
800 { 796 {
801 StreamReader r = File.OpenText(filename); 797 using (StreamReader r = File.OpenText(filename))
802 linemap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
803
804 string line;
805 while ((line = r.ReadLine()) != null)
806 { 798 {
807 String[] parts = line.Split(new Char[] { ',' }); 799 linemap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
808 int kk = System.Convert.ToInt32(parts[0]);
809 int kv = System.Convert.ToInt32(parts[1]);
810 int vk = System.Convert.ToInt32(parts[2]);
811 int vv = System.Convert.ToInt32(parts[3]);
812 800
813 KeyValuePair<int, int> k = new KeyValuePair<int, int>(kk, kv); 801 string line;
814 KeyValuePair<int, int> v = new KeyValuePair<int, int>(vk, vv); 802 while ((line = r.ReadLine()) != null)
803 {
804 String[] parts = line.Split(new Char[] { ',' });
805 int kk = System.Convert.ToInt32(parts[0]);
806 int kv = System.Convert.ToInt32(parts[1]);
807 int vk = System.Convert.ToInt32(parts[2]);
808 int vv = System.Convert.ToInt32(parts[3]);
809
810 KeyValuePair<int, int> k = new KeyValuePair<int, int>(kk, kv);
811 KeyValuePair<int, int> v = new KeyValuePair<int, int>(vk, vv);
815 812
816 linemap[k] = v; 813 linemap[k] = v;
814 }
817 } 815 }
818 } 816 }
819 catch 817 catch
820 { 818 {
821 linemap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>(); 819 linemap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
822 } 820 }
821
823 return linemap; 822 return linemap;
824 } 823 }
825 } 824 }
826} 825} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 9da2168..b983be9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -71,7 +71,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
71 private bool m_TimerQueued; 71 private bool m_TimerQueued;
72 private DateTime m_EventStart; 72 private DateTime m_EventStart;
73 private bool m_InEvent; 73 private bool m_InEvent;
74 private string m_Assembly; 74 private string m_assemblyPath;
75 private string m_dataPath;
75 private string m_CurrentEvent = String.Empty; 76 private string m_CurrentEvent = String.Empty;
76 private bool m_InSelfDelete; 77 private bool m_InSelfDelete;
77 private int m_MaxScriptQueue; 78 private int m_MaxScriptQueue;
@@ -244,12 +245,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
244 /// </summary> 245 /// </summary>
245 /// <param name='dom'></param> 246 /// <param name='dom'></param>
246 /// <param name='assembly'></param> 247 /// <param name='assembly'></param>
248 /// <param name='dataPath'>
249 /// Path for all script associated data (state, etc.). In a multi-region set up
250 /// with all scripts loading into the same AppDomain this may not be the same place as the DLL itself.
251 /// </param>
247 /// <param name='stateSource'></param> 252 /// <param name='stateSource'></param>
248 /// <returns>false if load failed, true if suceeded</returns> 253 /// <returns>false if load failed, true if suceeded</returns>
249 public bool Load(AppDomain dom, Assembly scriptAssembly, StateSource stateSource) 254 public bool Load(AppDomain dom, Assembly scriptAssembly, string dataPath, StateSource stateSource)
250 { 255 {
251 //m_Assembly = scriptAssembly.CodeBase; 256 m_assemblyPath = scriptAssembly.Location;
252 m_Assembly = scriptAssembly.Location; 257 m_dataPath = dataPath;
253 m_stateSource = stateSource; 258 m_stateSource = stateSource;
254 259
255 try 260 try
@@ -270,14 +275,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
270 constructorParams = null; 275 constructorParams = null;
271 } 276 }
272 277
273// m_log.DebugFormat(
274// "[SCRIP
275// scriptType.FullName, m_Assembly, Engine.World.Name);
276
277 if (dom != System.AppDomain.CurrentDomain) 278 if (dom != System.AppDomain.CurrentDomain)
278 m_Script 279 m_Script
279 = (IScript)dom.CreateInstanceAndUnwrap( 280 = (IScript)dom.CreateInstanceAndUnwrap(
280 Path.GetFileNameWithoutExtension(m_Assembly), 281 Path.GetFileNameWithoutExtension(m_assemblyPath),
281 scriptType.FullName, 282 scriptType.FullName,
282 false, 283 false,
283 BindingFlags.Default, 284 BindingFlags.Default,
@@ -305,7 +306,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
305 { 306 {
306 m_log.ErrorFormat( 307 m_log.ErrorFormat(
307 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}", 308 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}",
308 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, m_Assembly, e.Message, e.StackTrace); 309 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, scriptAssembly.Location, e.Message, e.StackTrace);
309 310
310 return false; 311 return false;
311 } 312 }
@@ -340,10 +341,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
340 341
341 m_SaveState = true; 342 m_SaveState = true;
342 343
343 string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), ItemID.ToString() + ".state"); 344 string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
344 345
345 if (File.Exists(savedState)) 346 if (File.Exists(savedState))
346 { 347 {
348// m_log.DebugFormat(
349// "[SCRIPT INSTANCE]: Found state for script {0} for {1} ({2}) at {3} in {4}",
350// ItemID, savedState, Part.Name, Part.ParentGroup.Name, Part.ParentGroup.Scene.Name);
351
347 string xml = String.Empty; 352 string xml = String.Empty;
348 353
349 try 354 try
@@ -385,12 +390,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
385 m_startedFromSavedState = true; 390 m_startedFromSavedState = true;
386 } 391 }
387 } 392 }
388 else 393// else
389 { 394// {
390 m_log.WarnFormat( 395// m_log.WarnFormat(
391 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.", 396// "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.",
392 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState); 397// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
393 } 398// }
394 } 399 }
395 catch (Exception e) 400 catch (Exception e)
396 { 401 {
@@ -401,11 +406,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
401 } 406 }
402// else 407// else
403// { 408// {
404// ScenePresence presence = Engine.World.GetScenePresence(part.OwnerID); 409// m_log.DebugFormat(
405 410// "[SCRIPT INSTANCE]: Did not find state for script {0} for {1} ({2}) at {3} in {4}",
406// if (presence != null && (!postOnRez)) 411// ItemID, savedState, Part.Name, Part.ParentGroup.Name, Part.ParentGroup.Scene.Name);
407// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
408
409// } 412// }
410 413
411 return true; 414 return true;
@@ -498,8 +501,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
498 501
499 public void RemoveState() 502 public void RemoveState()
500 { 503 {
501 string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), 504 string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
502 ItemID.ToString() + ".state"); 505
506// m_log.DebugFormat(
507// "[SCRIPT INSTANCE]: Deleting state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}.",
508// savedState, ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name);
503 509
504 try 510 try
505 { 511 {
@@ -822,8 +828,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
822 if (Engine.World.PipeEventsForScript(LocalID) || 828 if (Engine.World.PipeEventsForScript(LocalID) ||
823 data.EventName == "control") // Don't freeze avies! 829 data.EventName == "control") // Don't freeze avies!
824 { 830 {
825 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", 831// m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
826 // PrimName, ScriptName, data.EventName, State); 832// PrimName, ScriptName, data.EventName, State);
827 833
828 try 834 try
829 { 835 {
@@ -849,7 +855,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
849 // This will be the very first event we deliver 855 // This will be the very first event we deliver
850 // (state_entry) in default state 856 // (state_entry) in default state
851 // 857 //
852 SaveState(m_Assembly); 858 SaveState();
853 859
854 m_SaveState = false; 860 m_SaveState = false;
855 } 861 }
@@ -1043,7 +1049,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1043 return m_DetectParams[idx].Key; 1049 return m_DetectParams[idx].Key;
1044 } 1050 }
1045 1051
1046 public void SaveState(string assembly) 1052 public void SaveState()
1047 { 1053 {
1048 // If we're currently in an event, just tell it to save upon return 1054 // If we're currently in an event, just tell it to save upon return
1049 // 1055 //
@@ -1065,10 +1071,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1065 { 1071 {
1066 try 1072 try
1067 { 1073 {
1068 FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state")); 1074 using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state")))
1069 Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); 1075 {
1070 fs.Write(buf, 0, buf.Length); 1076 Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml);
1071 fs.Close(); 1077 fs.Write(buf, 0, buf.Length);
1078 }
1072 } 1079 }
1073 catch(Exception) 1080 catch(Exception)
1074 { 1081 {
@@ -1148,7 +1155,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1148 1155
1149 public string GetAssemblyName() 1156 public string GetAssemblyName()
1150 { 1157 {
1151 return m_Assembly; 1158 return m_assemblyPath;
1152 } 1159 }
1153 1160
1154 public string GetXMLState() 1161 public string GetXMLState()
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
index fe15157..878e571 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
@@ -40,10 +40,10 @@ using OpenSim.Tests.Common;
40namespace OpenSim.Region.ScriptEngine.XEngine.Tests 40namespace OpenSim.Region.ScriptEngine.XEngine.Tests
41{ 41{
42 /// <summary> 42 /// <summary>
43 /// XEngine tests. 43 /// Basic XEngine tests.
44 /// </summary> 44 /// </summary>
45 [TestFixture] 45 [TestFixture]
46 public class XEngineTest : OpenSimTestCase 46 public class XEngineBasicTests : OpenSimTestCase
47 { 47 {
48 private TestScene m_scene; 48 private TestScene m_scene;
49 private XEngine m_xEngine; 49 private XEngine m_xEngine;
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
28using System;
29using System.Threading;
30using Nini.Config;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Region.CoreModules.Framework.EntityTransfer;
35using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Tests.Common;
39
40namespace 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
128default
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/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index a4113d6..906c6ee 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
70 /// <remarks> 70 /// <remarks>
71 /// If DebugLevel >= 1, then we log every time that a script is started. 71 /// If DebugLevel >= 1, then we log every time that a script is started.
72 /// </remarks> 72 /// </remarks>
73// public int DebugLevel { get; set; } 73 public int DebugLevel { get; set; }
74 74
75 private SmartThreadPool m_ThreadPool; 75 private SmartThreadPool m_ThreadPool;
76 private int m_MaxScriptQueue; 76 private int m_MaxScriptQueue;
@@ -101,7 +101,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
101 private bool m_InitialStartup = true; 101 private bool m_InitialStartup = true;
102 private int m_ScriptFailCount; // Number of script fails since compile queue was last empty 102 private int m_ScriptFailCount; // Number of script fails since compile queue was last empty
103 private string m_ScriptErrorMessage; 103 private string m_ScriptErrorMessage;
104 private Dictionary<string, string> m_uniqueScripts = new Dictionary<string, string>();
105 private bool m_AppDomainLoading; 104 private bool m_AppDomainLoading;
106 private Dictionary<UUID,ArrayList> m_ScriptErrors = 105 private Dictionary<UUID,ArrayList> m_ScriptErrors =
107 new Dictionary<UUID,ArrayList>(); 106 new Dictionary<UUID,ArrayList>();
@@ -403,12 +402,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
403 + "Level >= 2, log event invocations.\n", 402 + "Level >= 2, log event invocations.\n",
404 HandleDebugScriptLogCommand); 403 HandleDebugScriptLogCommand);
405 404
406// MainConsole.Instance.Commands.AddCommand( 405 MainConsole.Instance.Commands.AddCommand(
407// "Debug", false, "debug xengine", "debug xengine [<level>]", 406 "Debug", false, "debug xengine log", "debug xengine log [<level>]",
408// "Turn on detailed xengine debugging.", 407 "Turn on detailed xengine debugging.",
409// "If level <= 0, then no extra logging is done.\n" 408 "If level <= 0, then no extra logging is done.\n"
410// + "If level >= 1, then we log every time that a script is started.", 409 + "If level >= 1, then we log every time that a script is started.",
411// HandleDebugLevelCommand); 410 HandleDebugLevelCommand);
412 } 411 }
413 412
414 private void HandleDebugScriptLogCommand(string module, string[] args) 413 private void HandleDebugScriptLogCommand(string module, string[] args)
@@ -451,26 +450,26 @@ namespace OpenSim.Region.ScriptEngine.XEngine
451 /// </summary> 450 /// </summary>
452 /// <param name="module"></param> 451 /// <param name="module"></param>
453 /// <param name="args"></param> 452 /// <param name="args"></param>
454// private void HandleDebugLevelCommand(string module, string[] args) 453 private void HandleDebugLevelCommand(string module, string[] args)
455// { 454 {
456// if (args.Length == 3) 455 if (args.Length <= 4)
457// { 456 {
458// int newDebug; 457 int newDebug;
459// if (int.TryParse(args[2], out newDebug)) 458 if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, args[3], out newDebug))
460// { 459 {
461// DebugLevel = newDebug; 460 DebugLevel = newDebug;
462// MainConsole.Instance.OutputFormat("Debug level set to {0}", newDebug); 461 MainConsole.Instance.OutputFormat("Debug level set to {0} in XEngine for region {1}", newDebug, m_Scene.Name);
463// } 462 }
464// } 463 }
465// else if (args.Length == 2) 464 else if (args.Length == 3)
466// { 465 {
467// MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel); 466 MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel);
468// } 467 }
469// else 468 else
470// { 469 {
471// MainConsole.Instance.Output("Usage: debug xengine 0..1"); 470 MainConsole.Instance.Output("Usage: debug xengine log <level>");
472// } 471 }
473// } 472 }
474 473
475 /// <summary> 474 /// <summary>
476 /// Parse the raw item id into a script instance from the command params if it's present. 475 /// Parse the raw item id into a script instance from the command params if it's present.
@@ -570,7 +569,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
570 } 569 }
571 570
572 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded); 571 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
573 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
574 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 572 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
575 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 573 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
576 sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads); 574 sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads);
@@ -716,22 +714,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
716 { 714 {
717 // Force a final state save 715 // Force a final state save
718 // 716 //
719 if (m_Assemblies.ContainsKey(instance.AssetID)) 717 try
720 { 718 {
721 string assembly = m_Assemblies[instance.AssetID]; 719 instance.SaveState();
722 720 }
723 try 721 catch (Exception e)
724 { 722 {
725 instance.SaveState(assembly); 723 m_log.Error(
726 } 724 string.Format(
727 catch (Exception e) 725 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
728 { 726 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
729 m_log.Error( 727 , e);
730 string.Format(
731 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
732 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
733 , e);
734 }
735 } 728 }
736 729
737 // Clear the event queue and abort the instance thread 730 // Clear the event queue and abort the instance thread
@@ -840,18 +833,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
840 833
841 foreach (IScriptInstance i in instances) 834 foreach (IScriptInstance i in instances)
842 { 835 {
843 string assembly = String.Empty;
844
845 lock (m_Scripts)
846 {
847 if (!m_Assemblies.ContainsKey(i.AssetID))
848 continue;
849 assembly = m_Assemblies[i.AssetID];
850 }
851
852 try 836 try
853 { 837 {
854 i.SaveState(assembly); 838 i.SaveState();
855 } 839 }
856 catch (Exception e) 840 catch (Exception e)
857 { 841 {
@@ -1001,12 +985,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1001 if (engine != ScriptEngineName) 985 if (engine != ScriptEngineName)
1002 return; 986 return;
1003 987
1004 // If we've seen this exact script text before, use that reference instead
1005 if (m_uniqueScripts.ContainsKey(script))
1006 script = m_uniqueScripts[script];
1007 else
1008 m_uniqueScripts[script] = script;
1009
1010 Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource}; 988 Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource};
1011 989
1012 if (stateSource == (int)StateSource.ScriptedRez) 990 if (stateSource == (int)StateSource.ScriptedRez)
@@ -1020,11 +998,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1020 } 998 }
1021 else 999 else
1022 { 1000 {
1023 m_CompileQueue.Enqueue(parms);
1024 lock (m_CompileDict) 1001 lock (m_CompileDict)
1025 {
1026 m_CompileDict[itemID] = 0; 1002 m_CompileDict[itemID] = 0;
1027 } 1003
1004 // This must occur after the m_CompileDict so that an existing compile thread cannot hit the check
1005 // in DoOnRezScript() before m_CompileDict has been updated.
1006 m_CompileQueue.Enqueue(parms);
1028 1007
1029// m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID); 1008// m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID);
1030 1009
@@ -1100,7 +1079,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1100 // due to a race condition 1079 // due to a race condition
1101 // 1080 //
1102 lock (m_CompileQueue) 1081 lock (m_CompileQueue)
1082 {
1103 m_CurrentCompile = null; 1083 m_CurrentCompile = null;
1084
1085 // This is to avoid a situation where the m_CompileQueue while loop above could complete but
1086 // OnRezScript() place a new script on the queue and check m_CurrentCompile = null before we hit
1087 // this section.
1088 if (m_CompileQueue.Count > 0)
1089 m_CurrentCompile = m_ThreadPool.QueueWorkItem(DoOnRezScriptQueue, null);
1090 }
1104 } 1091 }
1105 1092
1106 return null; 1093 return null;
@@ -1148,10 +1135,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1148 return false; 1135 return false;
1149 } 1136 }
1150 1137
1151 m_log.DebugFormat( 1138 if (DebugLevel > 0)
1152 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1139 m_log.DebugFormat(
1153 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1140 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1154 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1141 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1142 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1155 1143
1156 UUID assetID = item.AssetID; 1144 UUID assetID = item.AssetID;
1157 1145
@@ -1170,7 +1158,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1170 lock (m_AddingAssemblies) 1158 lock (m_AddingAssemblies)
1171 { 1159 {
1172 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assemblyPath, out linemap); 1160 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assemblyPath, out linemap);
1173 1161
1162// m_log.DebugFormat(
1163// "[XENGINE]: Found assembly path {0} onrez {1} in {2}",
1164// assemblyPath, item.ItemID, World.Name);
1165
1174 if (!m_AddingAssemblies.ContainsKey(assemblyPath)) { 1166 if (!m_AddingAssemblies.ContainsKey(assemblyPath)) {
1175 m_AddingAssemblies[assemblyPath] = 1; 1167 m_AddingAssemblies[assemblyPath] = 1;
1176 } else { 1168 } else {
@@ -1348,14 +1340,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1348 // simulator session if the script halt strategy has been changed. Instead, we'll continue with 1340 // simulator session if the script halt strategy has been changed. Instead, we'll continue with
1349 // the existing DLL and the new one will be used in the next simulator session. 1341 // the existing DLL and the new one will be used in the next simulator session.
1350 if (recompile) 1342 if (recompile)
1343 {
1344 m_log.DebugFormat(
1345 "[XEngine]: Recompiling script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5} to switch it to {6} termination. Will be active on next restart.",
1346 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1347 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.Name,
1348 m_coopTermination ? "co-op" : "abort");
1349
1351 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, true, out assemblyPath, out linemap); 1350 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, true, out assemblyPath, out linemap);
1351 }
1352 1352
1353 instance = new ScriptInstance(this, part, 1353 instance = new ScriptInstance(this, part,
1354 item, 1354 item,
1355 startParam, postOnRez, 1355 startParam, postOnRez,
1356 m_MaxScriptQueue); 1356 m_MaxScriptQueue);
1357 1357
1358 if (!instance.Load(m_AppDomains[appDomain], scriptAssembly, stateSource)) 1358 if (!instance.Load(
1359 m_AppDomains[appDomain], scriptAssembly,
1360 Path.Combine(ScriptEnginePath, World.RegionInfo.RegionID.ToString()), stateSource))
1359 return false; 1361 return false;
1360 1362
1361// if (DebugLevel >= 1) 1363// if (DebugLevel >= 1)
@@ -1586,7 +1588,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1586 1588
1587 IScriptInstance instance = (ScriptInstance) parms; 1589 IScriptInstance instance = (ScriptInstance) parms;
1588 1590
1589 //m_log.DebugFormat("[XEngine]: Processing event for {0}", instance); 1591// m_log.DebugFormat("[XEngine]: Processing event for {0}", instance);
1590 1592
1591 return instance.EventProcessor(); 1593 return instance.EventProcessor();
1592 } 1594 }
@@ -2155,7 +2157,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2155 catch (IOException ex) 2157 catch (IOException ex)
2156 { 2158 {
2157 // if there already exists a file at that location, it may be locked. 2159 // if there already exists a file at that location, it may be locked.
2158 m_log.ErrorFormat("[XEngine]: Linemap file {0} already exists! {1}", mappath, ex.Message); 2160 m_log.Error(
2161 string.Format("[XEngine]: Linemap file {0} could not be written. Exception ", mappath), ex);
2159 } 2162 }
2160 } 2163 }
2161 } 2164 }
@@ -2181,6 +2184,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2181 m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message); 2184 m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message);
2182 } 2185 }
2183 2186
2187// m_log.DebugFormat(
2188// "[XEngine]: Wrote state for script item with ID {0} at {1} in {2}", itemID, statepath, m_Scene.Name);
2189
2184 return true; 2190 return true;
2185 } 2191 }
2186 2192