aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2014-04-03 00:19:53 +0100
committerJustin Clark-Casey (justincc)2014-04-03 00:19:53 +0100
commite6d0dcd4e80275b96322eb10b31a2b339e4a2d17 (patch)
tree2563e97bad5770551262be0dacdc0dca771777b1 /OpenSim
parentString matching in REST handlers: must allow '-' as a separator, because the ... (diff)
downloadopensim-SC_OLD-e6d0dcd4e80275b96322eb10b31a2b339e4a2d17.zip
opensim-SC_OLD-e6d0dcd4e80275b96322eb10b31a2b339e4a2d17.tar.gz
opensim-SC_OLD-e6d0dcd4e80275b96322eb10b31a2b339e4a2d17.tar.bz2
opensim-SC_OLD-e6d0dcd4e80275b96322eb10b31a2b339e4a2d17.tar.xz
Fix bug where crossing to a neighbouring region and back again would trigger an exception, and a second recross would stop the user moving until relog
Also fixes an issue where sitting avatar counts became inaccurate after any cross. Part of the problem was due to cloning code using MemberwiseClone() but not resetting certain collection structures. Adds regression test for this case. In relation to http://opensimulator.org/mantis/view.php?id=7050
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs31
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs107
4 files changed, 138 insertions, 8 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index b70e9df..4dc724d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -552,12 +552,29 @@ namespace OpenSim.Region.Framework.Scenes
552 552
553 av.IsInTransit = true; 553 av.IsInTransit = true;
554 554
555 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; 555 // A temporary measure to allow regression tests to work.
556 d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); 556 // Quite possibly, all BeginInvoke() calls should be replaced by Util.FireAndForget
557 // or similar since BeginInvoke() always uses the system threadpool to launch
558 // threads rather than any replace threadpool that we might be using.
559 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
560 {
561 entityTransfer.CrossAgentToNewRegionAsync(av, val, destination, av.Flying, version);
562 CrossAgentToNewRegionCompleted(av);
563 }
564 else
565 {
566 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
567 d.BeginInvoke(
568 av, val, destination, av.Flying, version,
569 ar => CrossAgentToNewRegionCompleted(d.EndInvoke(ar)), null);
570 }
557 } 571 }
558 else 572 else
573 {
559 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); 574 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val);
575 }
560 } 576 }
577
561 avsToCross.Clear(); 578 avsToCross.Clear();
562 return; 579 return;
563 } 580 }
@@ -630,11 +647,8 @@ namespace OpenSim.Region.Framework.Scenes
630 set { RootPart.Velocity = value; } 647 set { RootPart.Velocity = value; }
631 } 648 }
632 649
633 private void CrossAgentToNewRegionCompleted(IAsyncResult iar) 650 private void CrossAgentToNewRegionCompleted(ScenePresence agent)
634 { 651 {
635 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
636 ScenePresence agent = icon.EndInvoke(iar);
637
638 //// If the cross was successful, this agent is a child agent 652 //// If the cross was successful, this agent is a child agent
639 if (agent.IsChildAgent) 653 if (agent.IsChildAgent)
640 { 654 {
@@ -1698,10 +1712,15 @@ namespace OpenSim.Region.Framework.Scenes
1698 /// <returns></returns> 1712 /// <returns></returns>
1699 public SceneObjectGroup Copy(bool userExposed) 1713 public SceneObjectGroup Copy(bool userExposed)
1700 { 1714 {
1715 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1716 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1717 // but not between regions on different simulators). Really, all copying should be done explicitly.
1701 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1718 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1719
1702 dupe.Backup = false; 1720 dupe.Backup = false;
1703 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1721 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1704 dupe.m_sittingAvatars = new List<UUID>(); 1722 dupe.m_sittingAvatars = new List<UUID>();
1723 dupe.m_linkedAvatars = new List<ScenePresence>();
1705 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1724 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1706 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1725 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1707 1726
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index db4e285..c06175e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1753,7 +1753,11 @@ namespace OpenSim.Region.Framework.Scenes
1753 /// <returns></returns> 1753 /// <returns></returns>
1754 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 1754 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1755 { 1755 {
1756 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1757 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1758 // but not between regions on different simulators). Really, all copying should be done explicitly.
1756 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone(); 1759 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone();
1760
1757 dupe.m_shape = m_shape.Copy(); 1761 dupe.m_shape = m_shape.Copy();
1758 dupe.m_regionHandle = m_regionHandle; 1762 dupe.m_regionHandle = m_regionHandle;
1759 if (userExposed) 1763 if (userExposed)
@@ -1799,6 +1803,8 @@ namespace OpenSim.Region.Framework.Scenes
1799 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 1803 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1800 dupe.Shape.ExtraParams = extraP; 1804 dupe.Shape.ExtraParams = extraP;
1801 1805
1806 dupe.m_sittingAvatars = new HashSet<OpenMetaverse.UUID>();
1807
1802 // safeguard actual copy is done in sog.copy 1808 // safeguard actual copy is done in sog.copy
1803 dupe.KeyframeMotion = null; 1809 dupe.KeyframeMotion = null;
1804 dupe.PayPrice = (int[])PayPrice.Clone(); 1810 dupe.PayPrice = (int[])PayPrice.Clone();
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 080cdb4..6386a45 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1023,6 +1023,7 @@ namespace OpenSim.Region.Framework.Scenes
1023 else 1023 else
1024 { 1024 {
1025 part.ParentGroup.AddAvatar(UUID); 1025 part.ParentGroup.AddAvatar(UUID);
1026 part.AddSittingAvatar(UUID);
1026 if (part.SitTargetPosition != Vector3.Zero) 1027 if (part.SitTargetPosition != Vector3.Zero)
1027 part.SitTargetAvatar = UUID; 1028 part.SitTargetAvatar = UUID;
1028 // ParentPosition = part.GetWorldPosition(); 1029 // ParentPosition = part.GetWorldPosition();
@@ -2848,7 +2849,6 @@ namespace OpenSim.Region.Framework.Scenes
2848 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2849 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2849 } 2850 }
2850 2851
2851
2852 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2852 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2853 { 2853 {
2854 if (IsChildAgent) 2854 if (IsChildAgent)
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs
index 4d07741..d65b0b6 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs
@@ -26,10 +26,12 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using Nini.Config; 30using Nini.Config;
30using NUnit.Framework; 31using NUnit.Framework;
31using OpenMetaverse; 32using OpenMetaverse;
32using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Region.CoreModules.Framework;
33using OpenSim.Region.CoreModules.Framework.EntityTransfer; 35using OpenSim.Region.CoreModules.Framework.EntityTransfer;
34using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 36using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
35using OpenSim.Region.CoreModules.World.Land; 37using OpenSim.Region.CoreModules.World.Land;
@@ -101,7 +103,110 @@ namespace OpenSim.Region.Framework.Scenes.Tests
101 /// Test cross with no prim limit module. 103 /// Test cross with no prim limit module.
102 /// </summary> 104 /// </summary>
103 /// <remarks> 105 /// <remarks>
104 /// XXX: This test may be better off in a specific PrimLimitsModuleTest class in optional module tests in the 106 /// Possibly this should belong in ScenePresenceCrossingTests, though here it is the object that is being moved
107 /// where the avatar is just a passenger.
108 /// </remarks>
109 [Test]
110 public void TestCrossOnSameSimulatorWithSittingAvatar()
111 {
112 TestHelpers.InMethod();
113// TestHelpers.EnableLogging();
114
115 UUID userId = TestHelpers.ParseTail(0x1);
116 int sceneObjectIdTail = 0x2;
117 Vector3 so1StartPos = new Vector3(128, 10, 20);
118
119 EntityTransferModule etmA = new EntityTransferModule();
120 EntityTransferModule etmB = new EntityTransferModule();
121 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
122
123 IConfigSource config = new IniConfigSource();
124 IConfig modulesConfig = config.AddConfig("Modules");
125 modulesConfig.Set("EntityTransferModule", etmA.Name);
126 modulesConfig.Set("SimulationServices", lscm.Name);
127 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
128
129 // In order to run a single threaded regression test we do not want the entity transfer module waiting
130 // for a callback from the destination scene before removing its avatar data.
131 entityTransferConfig.Set("wait_for_callback", false);
132
133 SceneHelpers sh = new SceneHelpers();
134 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
135 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
136
137 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
138 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
139 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
140
141 SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail);
142 UUID so1Id = so1.UUID;
143 so1.AbsolutePosition = so1StartPos;
144
145 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
146 TestClient tc = new TestClient(acd, sceneA);
147 List<TestClient> destinationTestClients = new List<TestClient>();
148 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
149
150 ScenePresence sp1SceneA = SceneHelpers.AddScenePresence(sceneA, tc, acd);
151 sp1SceneA.AbsolutePosition = so1StartPos;
152 sp1SceneA.HandleAgentRequestSit(sp1SceneA.ControllingClient, sp1SceneA.UUID, so1.UUID, Vector3.Zero);
153
154 // Cross
155 sceneA.SceneGraph.UpdatePrimGroupPosition(
156 so1.LocalId, new Vector3(so1StartPos.X, so1StartPos.Y - 20, so1StartPos.Z), userId);
157
158 SceneObjectGroup so1PostCross;
159
160 {
161 ScenePresence sp1SceneAPostCross = sceneA.GetScenePresence(userId);
162 Assert.IsTrue(sp1SceneAPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly false");
163
164 ScenePresence sp1SceneBPostCross = sceneB.GetScenePresence(userId);
165 TestClient sceneBTc = ((TestClient)sp1SceneBPostCross.ControllingClient);
166 sceneBTc.CompleteMovement();
167
168 Assert.IsFalse(sp1SceneBPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true");
169 Assert.IsTrue(sp1SceneBPostCross.IsSatOnObject);
170
171 Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id), "uck");
172 so1PostCross = sceneB.GetSceneObjectGroup(so1Id);
173 Assert.NotNull(so1PostCross);
174 Assert.AreEqual(1, so1PostCross.GetSittingAvatarsCount());
175 Assert.AreEqual(1, so1PostCross.GetLinkedAvatars().Count);
176 }
177
178 Vector3 so1PostCrossPos = so1PostCross.AbsolutePosition;
179
180// Console.WriteLine("CRISSCROSS");
181
182 // Recross
183 sceneB.SceneGraph.UpdatePrimGroupPosition(
184 so1PostCross.LocalId, new Vector3(so1PostCrossPos.X, so1PostCrossPos.Y + 20, so1PostCrossPos.Z), userId);
185
186 {
187 ScenePresence sp1SceneBPostReCross = sceneB.GetScenePresence(userId);
188 Assert.IsTrue(sp1SceneBPostReCross.IsChildAgent, "sp1SceneBPostReCross.IsChildAgent unexpectedly false");
189
190 ScenePresence sp1SceneAPostReCross = sceneA.GetScenePresence(userId);
191 TestClient sceneATc = ((TestClient)sp1SceneAPostReCross.ControllingClient);
192 sceneATc.CompleteMovement();
193
194 Assert.IsFalse(sp1SceneAPostReCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true");
195 Assert.IsTrue(sp1SceneAPostReCross.IsSatOnObject);
196
197 Assert.IsNull(sceneB.GetSceneObjectGroup(so1Id), "uck2");
198 SceneObjectGroup so1PostReCross = sceneA.GetSceneObjectGroup(so1Id);
199 Assert.NotNull(so1PostReCross);
200 Assert.AreEqual(1, so1PostReCross.GetSittingAvatarsCount());
201 Assert.AreEqual(1, so1PostReCross.GetLinkedAvatars().Count);
202 }
203 }
204
205 /// <summary>
206 /// Test cross with no prim limit module.
207 /// </summary>
208 /// <remarks>
209 /// XXX: This test may FCbe better off in a specific PrimLimitsModuleTest class in optional module tests in the
105 /// future (though it is configured as active by default, so not really optional). 210 /// future (though it is configured as active by default, so not really optional).
106 /// </remarks> 211 /// </remarks>
107 [Test] 212 [Test]