aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2013-03-22 01:00:13 +0000
committerJustin Clark-Casey (justincc)2013-03-22 01:00:13 +0000
commit7471bc77757ce0b294d04f0eb552dbc5ea749793 (patch)
tree11500087275dfe980377a3f06985e296ad35fb1b
parentImplement chat across region borders since we can tell if avatars in neighbou... (diff)
downloadopensim-SC_OLD-7471bc77757ce0b294d04f0eb552dbc5ea749793.zip
opensim-SC_OLD-7471bc77757ce0b294d04f0eb552dbc5ea749793.tar.gz
opensim-SC_OLD-7471bc77757ce0b294d04f0eb552dbc5ea749793.tar.bz2
opensim-SC_OLD-7471bc77757ce0b294d04f0eb552dbc5ea749793.tar.xz
At strategic points in the teleport process, if the client has simultaneously logged out then do not continue.
This aims to reduce any side effects if the process tries to complete after the client has logged back in (e.g. it was delayed due to a slow destination region response). This introduces a new Aborting entity transfer state which signals that the teleport should be stopped but no compensating actions performed.
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs20
2 files changed, 69 insertions, 10 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 82358d8..5713e88 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -167,6 +167,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
167 167
168 if (!DisableInterRegionTeleportCancellation) 168 if (!DisableInterRegionTeleportCancellation)
169 client.OnTeleportCancel += OnClientCancelTeleport; 169 client.OnTeleportCancel += OnClientCancelTeleport;
170
171 client.OnConnectionClosed += OnConnectionClosed;
170 } 172 }
171 173
172 public virtual void Close() {} 174 public virtual void Close() {}
@@ -185,6 +187,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
185 187
186 #region Agent Teleports 188 #region Agent Teleports
187 189
190 private void OnConnectionClosed(IClientAPI client)
191 {
192 if (client.IsLoggingOut)
193 {
194 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting);
195
196 m_log.DebugFormat(
197 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
198 client.Name, Scene.Name);
199 }
200 }
201
188 private void OnClientCancelTeleport(IClientAPI client) 202 private void OnClientCancelTeleport(IClientAPI client)
189 { 203 {
190 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling); 204 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling);
@@ -590,6 +604,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
590 return; 604 return;
591 } 605 }
592 606
607 Thread.Sleep(30000);
608
593 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) 609 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
594 { 610 {
595 m_log.DebugFormat( 611 m_log.DebugFormat(
@@ -598,6 +614,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
598 614
599 return; 615 return;
600 } 616 }
617 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
618 {
619 m_log.DebugFormat(
620 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
621 sp.Name, finalDestination.RegionName, sp.Scene.Name);
622
623 return;
624 }
601 625
602 // Past this point we have to attempt clean up if the teleport fails, so update transfer state. 626 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
603 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 627 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
@@ -657,12 +681,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
657 681
658 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); 682 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
659 683
684 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
685 // establish th econnection to the destination which makes it return true.
686 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
687 {
688 m_log.DebugFormat(
689 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
690 sp.Name, finalDestination.RegionName, sp.Scene.Name);
691
692 return;
693 }
694
660 // A common teleport failure occurs when we can send CreateAgent to the 695 // A common teleport failure occurs when we can send CreateAgent to the
661 // destination region but the viewer cannot establish the connection (e.g. due to network issues between 696 // destination region but the viewer cannot establish the connection (e.g. due to network issues between
662 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then 697 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
663 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). 698 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail().
664 if (!UpdateAgent(reg, finalDestination, agent, sp)) 699 if (!UpdateAgent(reg, finalDestination, agent, sp))
665 { 700 {
701 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
702 {
703 m_log.DebugFormat(
704 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
705 sp.Name, finalDestination.RegionName, sp.Scene.Name);
706
707 return;
708 }
709
666 m_log.WarnFormat( 710 m_log.WarnFormat(
667 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", 711 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.",
668 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 712 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
@@ -677,7 +721,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
677 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", 721 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
678 sp.Name, finalDestination.RegionName, sp.Scene.Name); 722 sp.Name, finalDestination.RegionName, sp.Scene.Name);
679 723
680 CleanupAbortedInterRegionTeleport(sp, finalDestination); 724 CleanupFailedInterRegionTeleport(sp, finalDestination);
681 725
682 return; 726 return;
683 } 727 }
@@ -706,6 +750,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
706 // that the client contacted the destination before we close things here. 750 // that the client contacted the destination before we close things here.
707 if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) 751 if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
708 { 752 {
753 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
754 {
755 m_log.DebugFormat(
756 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
757 sp.Name, finalDestination.RegionName, sp.Scene.Name);
758
759 return;
760 }
761
709 m_log.WarnFormat( 762 m_log.WarnFormat(
710 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", 763 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
711 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 764 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
@@ -772,7 +825,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
772 /// <remarks> 825 /// <remarks>
773 /// <param name='sp'> </param> 826 /// <param name='sp'> </param>
774 /// <param name='finalDestination'></param> 827 /// <param name='finalDestination'></param>
775 protected virtual void CleanupAbortedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) 828 protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination)
776 { 829 {
777 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); 830 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
778 831
@@ -794,7 +847,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
794 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> 847 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param>
795 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) 848 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason)
796 { 849 {
797 CleanupAbortedInterRegionTeleport(sp, finalDestination); 850 CleanupFailedInterRegionTeleport(sp, finalDestination);
798 851
799 sp.ControllingClient.SendTeleportFailed( 852 sp.ControllingClient.SendTeleportFailed(
800 string.Format( 853 string.Format(
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
index 7314727..fc02916 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -51,11 +51,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
51 /// This is a state machine. 51 /// This is a state machine.
52 /// 52 ///
53 /// [Entry] => Preparing 53 /// [Entry] => Preparing
54 /// Preparing => { Transferring || Cancelling || CleaningUp || [Exit] } 54 /// Preparing => { Transferring || Cancelling || CleaningUp || Aborting || [Exit] }
55 /// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp } 55 /// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp || Aborting }
56 /// Cancelling => CleaningUp 56 /// Cancelling => CleaningUp || Aborting
57 /// ReceivedAtDestination => CleaningUp 57 /// ReceivedAtDestination => CleaningUp || Aborting
58 /// CleaningUp => [Exit] 58 /// CleaningUp => [Exit]
59 /// Aborting => [Exit]
59 /// 60 ///
60 /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp 61 /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
61 /// However, any state can transition to CleaningUp if the teleport has failed. 62 /// However, any state can transition to CleaningUp if the teleport has failed.
@@ -66,7 +67,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
66 Transferring, // The agent is in the process of being transferred to a destination 67 Transferring, // The agent is in the process of being transferred to a destination
67 ReceivedAtDestination, // The destination has notified us that the agent has been successfully received 68 ReceivedAtDestination, // The destination has notified us that the agent has been successfully received
68 CleaningUp, // The agent is being changed to child/removed after a transfer 69 CleaningUp, // The agent is being changed to child/removed after a transfer
69 Cancelling // The user has cancelled the teleport but we have yet to act upon this. 70 Cancelling, // The user has cancelled the teleport but we have yet to act upon this.
71 Aborting // The transfer is aborting. Unlike Cancelling, no compensating actions should be performed
70 } 72 }
71 73
72 /// <summary> 74 /// <summary>
@@ -134,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
134 // Illegal to try and update an agent that's not actually in transit. 136 // Illegal to try and update an agent that's not actually in transit.
135 if (!m_agentsInTransit.ContainsKey(id)) 137 if (!m_agentsInTransit.ContainsKey(id))
136 { 138 {
137 if (newState != AgentTransferState.Cancelling) 139 if (newState != AgentTransferState.Cancelling && newState != AgentTransferState.Aborting)
138 failureMessage = string.Format( 140 failureMessage = string.Format(
139 "Agent with ID {0} is not registered as in transit in {1}", 141 "Agent with ID {0} is not registered as in transit in {1}",
140 id, m_mod.Scene.RegionInfo.RegionName); 142 id, m_mod.Scene.RegionInfo.RegionName);
@@ -145,7 +147,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
145 { 147 {
146 oldState = m_agentsInTransit[id]; 148 oldState = m_agentsInTransit[id];
147 149
148 if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) 150 if (newState == AgentTransferState.Aborting)
151 {
152 transitionOkay = true;
153 }
154 else if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
149 { 155 {
150 transitionOkay = true; 156 transitionOkay = true;
151 } 157 }