aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs59
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs15
2 files changed, 67 insertions, 7 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 051c617..3eaa8fd 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3695,10 +3695,13 @@ namespace OpenSim.Region.Framework.Scenes
3695 3695
3696 // We need to ensure that we are not already removing the scene presence before we ask it not to be 3696 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3697 // closed. 3697 // closed.
3698 if (sp != null && sp.IsChildAgent && sp.LifecycleState == ScenePresenceState.Running) 3698 if (sp != null && sp.IsChildAgent
3699 && (sp.LifecycleState == ScenePresenceState.Running
3700 || sp.LifecycleState == ScenePresenceState.PreRemove))
3699 { 3701 {
3700 m_log.DebugFormat( 3702 m_log.DebugFormat(
3701 "[SCENE]: Reusing existing child scene presence for {0} in {1}", sp.Name, Name); 3703 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3704 sp.Name, sp.LifecycleState, Name);
3702 3705
3703 // In the case where, for example, an A B C D region layout, an avatar may 3706 // In the case where, for example, an A B C D region layout, an avatar may
3704 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C 3707 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
@@ -3720,6 +3723,8 @@ namespace OpenSim.Region.Framework.Scenes
3720// } 3723// }
3721// else if (EntityTransferModule.IsInTransit(sp.UUID)) 3724// else if (EntityTransferModule.IsInTransit(sp.UUID))
3722 3725
3726 sp.LifecycleState = ScenePresenceState.Running;
3727
3723 if (EntityTransferModule.IsInTransit(sp.UUID)) 3728 if (EntityTransferModule.IsInTransit(sp.UUID))
3724 { 3729 {
3725 sp.DoNotCloseAfterTeleport = true; 3730 sp.DoNotCloseAfterTeleport = true;
@@ -4454,6 +4459,50 @@ namespace OpenSim.Region.Framework.Scenes
4454 } 4459 }
4455 4460
4456 /// <summary> 4461 /// <summary>
4462 /// Tell a single agent to prepare to close.
4463 /// </summary>
4464 /// <remarks>
4465 /// This should only be called if we may close the agent but there will be some delay in so doing. Meant for
4466 /// internal use - other callers should almost certainly called IncomingCloseAgent().
4467 /// </remarks>
4468 /// <param name="sp"></param>
4469 /// <returns>true if pre-close state notification was successful. false if the agent
4470 /// was not in a state where it could transition to pre-close.</returns>
4471 public bool IncomingPreCloseAgent(ScenePresence sp)
4472 {
4473 lock (m_removeClientLock)
4474 {
4475 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4476 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4477 // want to obey this close since C may have renewed the child agent lease on B.
4478 if (sp.DoNotCloseAfterTeleport)
4479 {
4480 m_log.DebugFormat(
4481 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4482 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4483
4484 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4485 sp.DoNotCloseAfterTeleport = false;
4486
4487 return false;
4488 }
4489
4490 if (sp.LifecycleState != ScenePresenceState.Running)
4491 {
4492 m_log.DebugFormat(
4493 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4494 sp.Name, Name, sp.LifecycleState);
4495
4496 return false;
4497 }
4498
4499 sp.LifecycleState = ScenePresenceState.PreRemove;
4500
4501 return true;
4502 }
4503 }
4504
4505 /// <summary>
4457 /// Tell a single agent to disconnect from the region. 4506 /// Tell a single agent to disconnect from the region.
4458 /// </summary> 4507 /// </summary>
4459 /// <param name="agentID"></param> 4508 /// <param name="agentID"></param>
@@ -4472,16 +4521,16 @@ namespace OpenSim.Region.Framework.Scenes
4472 if (sp == null) 4521 if (sp == null)
4473 { 4522 {
4474 m_log.DebugFormat( 4523 m_log.DebugFormat(
4475 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in {1}", 4524 "[SCENE]: Called IncomingCloseAgent() with agent ID {0} but no such presence is in {1}",
4476 agentID, Name); 4525 agentID, Name);
4477 4526
4478 return false; 4527 return false;
4479 } 4528 }
4480 4529
4481 if (sp.LifecycleState != ScenePresenceState.Running) 4530 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4482 { 4531 {
4483 m_log.DebugFormat( 4532 m_log.DebugFormat(
4484 "[SCENE]: Called RemoveClient() for {0} in {1} but presence is already in state {2}", 4533 "[SCENE]: Called IncomingCloseAgent() for {0} in {1} but presence is already in state {2}",
4485 sp.Name, Name, sp.LifecycleState); 4534 sp.Name, Name, sp.LifecycleState);
4486 4535
4487 return false; 4536 return false;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
index dc3a212..cae7fe5 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -37,7 +37,8 @@ namespace OpenSim.Region.Framework.Scenes
37 /// This is a state machine. 37 /// This is a state machine.
38 /// 38 ///
39 /// [Entry] => Running 39 /// [Entry] => Running
40 /// Running => Removing 40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing
41 /// Removing => Removed 42 /// Removing => Removed
42 /// 43 ///
43 /// All other methods should only see the scene presence in running state - this is the normal operational state 44 /// All other methods should only see the scene presence in running state - this is the normal operational state
@@ -46,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes
46 public enum ScenePresenceState 47 public enum ScenePresenceState
47 { 48 {
48 Running, // Normal operation state. The scene presence is available. 49 Running, // Normal operation state. The scene presence is available.
50 PreRemove, // The presence is due to be removed but can still be returning to running.
49 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient. 51 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
50 Removed, // The presence has been removed from the scene and is effectively dead. 52 Removed, // The presence has been removed from the scene and is effectively dead.
51 // There is no exit from this state. 53 // There is no exit from this state.
@@ -80,8 +82,17 @@ namespace OpenSim.Region.Framework.Scenes
80 82
81 lock (this) 83 lock (this)
82 { 84 {
83 if (newState == ScenePresenceState.Removing && m_state == ScenePresenceState.Running) 85 if (newState == m_state)
86 return;
87 else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
84 transitionOkay = true; 88 transitionOkay = true;
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing)
92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true;
95 }
85 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing) 96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
86 transitionOkay = true; 97 transitionOkay = true;
87 } 98 }