aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2015-01-16 22:44:54 +0000
committerJustin Clark-Casey (justincc)2015-01-16 22:46:48 +0000
commit8d724e90de0fb3b406f82f4e06b6f5b79c5a538c (patch)
tree069eac2d8fa46b63267d4119795a6cabf218c97f /OpenSim/Region/ScriptEngine
parentminor: Suppress the log messages when user profiles data is requested for an ... (diff)
downloadopensim-SC_OLD-8d724e90de0fb3b406f82f4e06b6f5b79c5a538c.zip
opensim-SC_OLD-8d724e90de0fb3b406f82f4e06b6f5b79c5a538c.tar.gz
opensim-SC_OLD-8d724e90de0fb3b406f82f4e06b6f5b79c5a538c.tar.bz2
opensim-SC_OLD-8d724e90de0fb3b406f82f4e06b6f5b79c5a538c.tar.xz
For scripts in attachments, don't save .state files apart from the initial one as these are ignored since .state is saved in the attachment's asset.
This eliminates pointless work and exceptions when an appdomain is unloaded whilst an attachment script state is persisted. Adds test for this case. Relates to http://opensimulator.org/mantis/view.php?id=7407
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs27
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs152
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs18
4 files changed, 195 insertions, 8 deletions
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index 1097efb..35e5f18 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -98,6 +98,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
98 string State { get; set; } 98 string State { get; set; }
99 99
100 /// <summary> 100 /// <summary>
101 /// If true then the engine is responsible for persisted state. If false then some other component may
102 /// persist state (e.g. attachments persisting in assets).
103 /// </summary>
104 bool StatePersistedHere { get; }
105
106 /// <summary>
101 /// Time the script was last started 107 /// Time the script was last started
102 /// </summary> 108 /// </summary>
103 DateTime TimeStarted { get; } 109 DateTime TimeStarted { get; }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 79e4774..9498aa8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -58,6 +58,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
58 { 58 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60 60
61 public bool StatePersistedHere { get { return m_AttachedAvatar == UUID.Zero; } }
62
61 /// <summary> 63 /// <summary>
62 /// The current work item if an event for this script is running or waiting to run, 64 /// The current work item if an event for this script is running or waiting to run,
63 /// </summary> 65 /// </summary>
@@ -76,7 +78,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
76 private string m_CurrentEvent = String.Empty; 78 private string m_CurrentEvent = String.Empty;
77 private bool m_InSelfDelete; 79 private bool m_InSelfDelete;
78 private int m_MaxScriptQueue; 80 private int m_MaxScriptQueue;
79 private bool m_SaveState = true; 81 private bool m_SaveState;
80 private int m_ControlEventsInQueue; 82 private int m_ControlEventsInQueue;
81 private int m_LastControlLevel; 83 private int m_LastControlLevel;
82 private bool m_CollisionInQueue; 84 private bool m_CollisionInQueue;
@@ -238,6 +240,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
238 m_postOnRez = postOnRez; 240 m_postOnRez = postOnRez;
239 m_AttachedAvatar = Part.ParentGroup.AttachedAvatar; 241 m_AttachedAvatar = Part.ParentGroup.AttachedAvatar;
240 m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID; 242 m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID;
243
244 m_SaveState = StatePersistedHere;
245
246// m_log.DebugFormat(
247// "[SCRIPT INSTANCE]: Instantiated script instance {0} (id {1}) in part {2} (id {3}) in object {4} attached avatar {5} in {6}",
248// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, m_AttachedAvatar, Engine.World.Name);
241 } 249 }
242 250
243 /// <summary> 251 /// <summary>
@@ -339,8 +347,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
339 return false; 347 return false;
340 } 348 }
341 349
342 m_SaveState = true; 350 // For attachments, XEngine saves the state into a .state file when XEngine.SetXMLState() is called.
343
344 string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state"); 351 string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
345 352
346 if (File.Exists(savedState)) 353 if (File.Exists(savedState))
@@ -389,6 +396,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
389 m_SaveState = false; 396 m_SaveState = false;
390 m_startedFromSavedState = true; 397 m_startedFromSavedState = true;
391 } 398 }
399
400 // If this script is in an attachment then we no longer need the state file.
401 if (!StatePersistedHere)
402 RemoveState();
392 } 403 }
393// else 404// else
394// { 405// {
@@ -984,7 +995,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
984 (int)m_Script.GetStateEventFlags(State)); 995 (int)m_Script.GetStateEventFlags(State));
985 if (running) 996 if (running)
986 Start(); 997 Start();
987 m_SaveState = true; 998
999 m_SaveState = StatePersistedHere;
1000
988 PostEvent(new EventParams("state_entry", 1001 PostEvent(new EventParams("state_entry",
989 new Object[0], new DetectParams[0])); 1002 new Object[0], new DetectParams[0]));
990 } 1003 }
@@ -1010,7 +1023,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1010 1023
1011 if (m_CurrentEvent != "state_entry") 1024 if (m_CurrentEvent != "state_entry")
1012 { 1025 {
1013 m_SaveState = true; 1026 m_SaveState = StatePersistedHere;
1014 PostEvent(new EventParams("state_entry", 1027 PostEvent(new EventParams("state_entry",
1015 new Object[0], new DetectParams[0])); 1028 new Object[0], new DetectParams[0]));
1016 throw new EventAbortException(); 1029 throw new EventAbortException();
@@ -1060,6 +1073,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1060 return; 1073 return;
1061 } 1074 }
1062 1075
1076// m_log.DebugFormat(
1077// "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}",
1078// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name);
1079
1063 PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); 1080 PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID);
1064 1081
1065 string xml = ScriptSerializer.Serialize(this); 1082 string xml = ScriptSerializer.Serialize(this);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs
new file mode 100644
index 0000000..5b7e5f7
--- /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
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Linq;
32using System.Threading;
33using Nini.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Avatar.Attachments;
38using OpenSim.Region.CoreModules.Framework.InventoryAccess;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.ScriptEngine.XEngine;
41using OpenSim.Services.Interfaces;
42using OpenSim.Tests.Common;
43
44namespace 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,
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 f87d631..03fafed 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -718,7 +718,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
718 // 718 //
719 try 719 try
720 { 720 {
721 instance.SaveState(); 721 if (instance.StatePersistedHere)
722 instance.SaveState();
722 } 723 }
723 catch (Exception e) 724 catch (Exception e)
724 { 725 {
@@ -830,7 +831,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
830 lock (m_Scripts) 831 lock (m_Scripts)
831 { 832 {
832 foreach (IScriptInstance instance in m_Scripts.Values) 833 foreach (IScriptInstance instance in m_Scripts.Values)
833 instances.Add(instance); 834 {
835 if (instance.StatePersistedHere)
836 {
837// m_log.DebugFormat(
838// "[XEngine]: Adding script {0}.{1}, item UUID {2}, prim UUID {3} in {4} for state persistence",
839// instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name);
840
841 instances.Add(instance);
842 }
843 }
834 } 844 }
835 845
836 foreach (IScriptInstance i in instances) 846 foreach (IScriptInstance i in instances)
@@ -1457,7 +1467,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1457 } 1467 }
1458 } 1468 }
1459 1469
1460 instance.RemoveState(); 1470 if (instance.StatePersistedHere)
1471 instance.RemoveState();
1472
1461 instance.DestroyScriptInstance(); 1473 instance.DestroyScriptInstance();
1462 1474
1463 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 1475 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);