diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework')
16 files changed, 949 insertions, 184 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs index 7f30e5a..2eb9bfb 100644 --- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs | |||
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.Framework | |||
55 | /// <summary> | 55 | /// <summary> |
56 | /// Each agent has its own capabilities handler. | 56 | /// Each agent has its own capabilities handler. |
57 | /// </summary> | 57 | /// </summary> |
58 | protected Dictionary<UUID, Caps> m_capsObjects = new Dictionary<UUID, Caps>(); | 58 | protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>(); |
59 | 59 | ||
60 | protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>(); | 60 | protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>(); |
61 | protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds | 61 | protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds |
@@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.Framework | |||
100 | get { return null; } | 100 | get { return null; } |
101 | } | 101 | } |
102 | 102 | ||
103 | public void CreateCaps(UUID agentId) | 103 | public void CreateCaps(UUID agentId, uint circuitCode) |
104 | { | 104 | { |
105 | int flags = m_scene.GetUserFlags(agentId); | 105 | int flags = m_scene.GetUserFlags(agentId); |
106 | if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags)) | 106 | if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags)) |
@@ -108,9 +108,9 @@ namespace OpenSim.Region.CoreModules.Framework | |||
108 | 108 | ||
109 | String capsObjectPath = GetCapsPath(agentId); | 109 | String capsObjectPath = GetCapsPath(agentId); |
110 | 110 | ||
111 | if (m_capsObjects.ContainsKey(agentId)) | 111 | if (m_capsObjects.ContainsKey(circuitCode)) |
112 | { | 112 | { |
113 | Caps oldCaps = m_capsObjects[agentId]; | 113 | Caps oldCaps = m_capsObjects[circuitCode]; |
114 | 114 | ||
115 | m_log.DebugFormat( | 115 | m_log.DebugFormat( |
116 | "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ", | 116 | "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ", |
@@ -125,12 +125,12 @@ namespace OpenSim.Region.CoreModules.Framework | |||
125 | (MainServer.Instance == null) ? 0: MainServer.Instance.Port, | 125 | (MainServer.Instance == null) ? 0: MainServer.Instance.Port, |
126 | capsObjectPath, agentId, m_scene.RegionInfo.RegionName); | 126 | capsObjectPath, agentId, m_scene.RegionInfo.RegionName); |
127 | 127 | ||
128 | m_capsObjects[agentId] = caps; | 128 | m_capsObjects[circuitCode] = caps; |
129 | 129 | ||
130 | m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); | 130 | m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); |
131 | } | 131 | } |
132 | 132 | ||
133 | public void RemoveCaps(UUID agentId) | 133 | public void RemoveCaps(UUID agentId, uint circuitCode) |
134 | { | 134 | { |
135 | if (childrenSeeds.ContainsKey(agentId)) | 135 | if (childrenSeeds.ContainsKey(agentId)) |
136 | { | 136 | { |
@@ -139,11 +139,11 @@ namespace OpenSim.Region.CoreModules.Framework | |||
139 | 139 | ||
140 | lock (m_capsObjects) | 140 | lock (m_capsObjects) |
141 | { | 141 | { |
142 | if (m_capsObjects.ContainsKey(agentId)) | 142 | if (m_capsObjects.ContainsKey(circuitCode)) |
143 | { | 143 | { |
144 | m_capsObjects[agentId].DeregisterHandlers(); | 144 | m_capsObjects[circuitCode].DeregisterHandlers(); |
145 | m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]); | 145 | m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[circuitCode]); |
146 | m_capsObjects.Remove(agentId); | 146 | m_capsObjects.Remove(circuitCode); |
147 | } | 147 | } |
148 | else | 148 | else |
149 | { | 149 | { |
@@ -154,19 +154,30 @@ namespace OpenSim.Region.CoreModules.Framework | |||
154 | } | 154 | } |
155 | } | 155 | } |
156 | 156 | ||
157 | public Caps GetCapsForUser(UUID agentId) | 157 | public Caps GetCapsForUser(uint circuitCode) |
158 | { | 158 | { |
159 | lock (m_capsObjects) | 159 | lock (m_capsObjects) |
160 | { | 160 | { |
161 | if (m_capsObjects.ContainsKey(agentId)) | 161 | if (m_capsObjects.ContainsKey(circuitCode)) |
162 | { | 162 | { |
163 | return m_capsObjects[agentId]; | 163 | return m_capsObjects[circuitCode]; |
164 | } | 164 | } |
165 | } | 165 | } |
166 | 166 | ||
167 | return null; | 167 | return null; |
168 | } | 168 | } |
169 | 169 | ||
170 | public void ActivateCaps(uint circuitCode) | ||
171 | { | ||
172 | lock (m_capsObjects) | ||
173 | { | ||
174 | if (m_capsObjects.ContainsKey(circuitCode)) | ||
175 | { | ||
176 | m_capsObjects[circuitCode].Activate(); | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
170 | public void SetAgentCapsSeeds(AgentCircuitData agent) | 181 | public void SetAgentCapsSeeds(AgentCircuitData agent) |
171 | { | 182 | { |
172 | capsPaths[agent.AgentID] = agent.CapsPath; | 183 | capsPaths[agent.AgentID] = agent.CapsPath; |
@@ -237,9 +248,9 @@ namespace OpenSim.Region.CoreModules.Framework | |||
237 | StringBuilder caps = new StringBuilder(); | 248 | StringBuilder caps = new StringBuilder(); |
238 | caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); | 249 | caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); |
239 | 250 | ||
240 | foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) | 251 | foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects) |
241 | { | 252 | { |
242 | caps.AppendFormat("** User {0}:\n", kvp.Key); | 253 | caps.AppendFormat("** Circuit {0}:\n", kvp.Key); |
243 | 254 | ||
244 | for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); ) | 255 | for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); ) |
245 | { | 256 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs new file mode 100644 index 0000000..1f1568f --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs | |||
@@ -0,0 +1,119 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using log4net; | ||
32 | using Mono.Addins; | ||
33 | using Nini.Config; | ||
34 | using OpenMetaverse; | ||
35 | using OpenMetaverse.Packets; | ||
36 | using OpenMetaverse.StructuredData; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Region.Framework; | ||
39 | using OpenSim.Region.Framework.Interfaces; | ||
40 | using OpenSim.Region.Framework.Scenes; | ||
41 | |||
42 | namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule | ||
43 | { | ||
44 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] | ||
45 | public class DAExampleModule : INonSharedRegionModule | ||
46 | { | ||
47 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
48 | |||
49 | private static readonly bool ENABLED = false; // enable for testing | ||
50 | |||
51 | public const string DANamespace = "DAExample Module"; | ||
52 | |||
53 | protected Scene m_scene; | ||
54 | protected IDialogModule m_dialogMod; | ||
55 | |||
56 | public string Name { get { return "DAExample Module"; } } | ||
57 | public Type ReplaceableInterface { get { return null; } } | ||
58 | |||
59 | public void Initialise(IConfigSource source) {} | ||
60 | |||
61 | public void AddRegion(Scene scene) | ||
62 | { | ||
63 | if (ENABLED) | ||
64 | { | ||
65 | m_scene = scene; | ||
66 | m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove; | ||
67 | m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | public void RemoveRegion(Scene scene) | ||
72 | { | ||
73 | if (ENABLED) | ||
74 | { | ||
75 | m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | public void RegionLoaded(Scene scene) {} | ||
80 | |||
81 | public void Close() | ||
82 | { | ||
83 | RemoveRegion(m_scene); | ||
84 | } | ||
85 | |||
86 | protected bool OnSceneGroupMove(UUID groupId, Vector3 delta) | ||
87 | { | ||
88 | OSDMap attrs = null; | ||
89 | SceneObjectPart sop = m_scene.GetSceneObjectPart(groupId); | ||
90 | |||
91 | if (sop == null) | ||
92 | return true; | ||
93 | |||
94 | if (!sop.DynAttrs.TryGetValue(DANamespace, out attrs)) | ||
95 | attrs = new OSDMap(); | ||
96 | |||
97 | OSDInteger newValue; | ||
98 | |||
99 | // We have to lock on the entire dynamic attributes map to avoid race conditions with serialization code. | ||
100 | lock (sop.DynAttrs) | ||
101 | { | ||
102 | if (!attrs.ContainsKey("moves")) | ||
103 | newValue = new OSDInteger(1); | ||
104 | else | ||
105 | newValue = new OSDInteger(attrs["moves"].AsInteger() + 1); | ||
106 | |||
107 | attrs["moves"] = newValue; | ||
108 | |||
109 | sop.DynAttrs[DANamespace] = attrs; | ||
110 | } | ||
111 | |||
112 | sop.ParentGroup.HasGroupChanged = true; | ||
113 | |||
114 | m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue)); | ||
115 | |||
116 | return true; | ||
117 | } | ||
118 | } | ||
119 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs new file mode 100644 index 0000000..650aa35 --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs | |||
@@ -0,0 +1,139 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using log4net; | ||
32 | using Mono.Addins; | ||
33 | using Nini.Config; | ||
34 | using OpenMetaverse; | ||
35 | using OpenMetaverse.Packets; | ||
36 | using OpenMetaverse.StructuredData; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Region.Framework; | ||
39 | using OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule; | ||
40 | using OpenSim.Region.Framework.Interfaces; | ||
41 | using OpenSim.Region.Framework.Scenes; | ||
42 | |||
43 | namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule | ||
44 | { | ||
45 | /// <summary> | ||
46 | /// Example module for experimenting with and demonstrating dynamic object ideas. | ||
47 | /// </summary> | ||
48 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DOExampleModule")] | ||
49 | public class DOExampleModule : INonSharedRegionModule | ||
50 | { | ||
51 | public class MyObject | ||
52 | { | ||
53 | public int Moves { get; set; } | ||
54 | |||
55 | public MyObject(int moves) | ||
56 | { | ||
57 | Moves = moves; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
62 | |||
63 | private static readonly bool ENABLED = false; // enable for testing | ||
64 | |||
65 | private Scene m_scene; | ||
66 | private IDialogModule m_dialogMod; | ||
67 | |||
68 | public string Name { get { return "DOExample Module"; } } | ||
69 | public Type ReplaceableInterface { get { return null; } } | ||
70 | |||
71 | public void Initialise(IConfigSource source) {} | ||
72 | |||
73 | public void AddRegion(Scene scene) | ||
74 | { | ||
75 | if (ENABLED) | ||
76 | { | ||
77 | m_scene = scene; | ||
78 | m_scene.EventManager.OnObjectAddedToScene += OnObjectAddedToScene; | ||
79 | m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove; | ||
80 | m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | public void RemoveRegion(Scene scene) | ||
85 | { | ||
86 | if (ENABLED) | ||
87 | { | ||
88 | m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | public void RegionLoaded(Scene scene) {} | ||
93 | |||
94 | public void Close() | ||
95 | { | ||
96 | RemoveRegion(m_scene); | ||
97 | } | ||
98 | |||
99 | private void OnObjectAddedToScene(SceneObjectGroup so) | ||
100 | { | ||
101 | SceneObjectPart rootPart = so.RootPart; | ||
102 | |||
103 | OSDMap attrs; | ||
104 | |||
105 | int movesSoFar = 0; | ||
106 | |||
107 | // Console.WriteLine("Here for {0}", so.Name); | ||
108 | |||
109 | if (rootPart.DynAttrs.TryGetValue(DAExampleModule.DANamespace, out attrs)) | ||
110 | { | ||
111 | movesSoFar = attrs["moves"].AsInteger(); | ||
112 | |||
113 | m_log.DebugFormat( | ||
114 | "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name); | ||
115 | } | ||
116 | |||
117 | rootPart.DynObjs.Add(Name, new MyObject(movesSoFar)); | ||
118 | } | ||
119 | |||
120 | private bool OnSceneGroupMove(UUID groupId, Vector3 delta) | ||
121 | { | ||
122 | SceneObjectGroup so = m_scene.GetSceneObjectGroup(groupId); | ||
123 | |||
124 | if (so == null) | ||
125 | return true; | ||
126 | |||
127 | object rawObj = so.RootPart.DynObjs.Get(Name); | ||
128 | |||
129 | if (rawObj != null) | ||
130 | { | ||
131 | MyObject myObj = (MyObject)rawObj; | ||
132 | |||
133 | m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", so.Name, so.UUID, ++myObj.Moves)); | ||
134 | } | ||
135 | |||
136 | return true; | ||
137 | } | ||
138 | } | ||
139 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index cb09047..b70aeb7 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -33,6 +33,7 @@ using System.Threading; | |||
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Framework.Capabilities; | 34 | using OpenSim.Framework.Capabilities; |
35 | using OpenSim.Framework.Client; | 35 | using OpenSim.Framework.Client; |
36 | using OpenSim.Framework.Monitoring; | ||
36 | using OpenSim.Region.Framework.Interfaces; | 37 | using OpenSim.Region.Framework.Interfaces; |
37 | using OpenSim.Region.Framework.Scenes; | 38 | using OpenSim.Region.Framework.Scenes; |
38 | using OpenSim.Region.Physics.Manager; | 39 | using OpenSim.Region.Physics.Manager; |
@@ -66,6 +67,42 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
66 | /// </summary> | 67 | /// </summary> |
67 | public bool WaitForAgentArrivedAtDestination { get; set; } | 68 | public bool WaitForAgentArrivedAtDestination { get; set; } |
68 | 69 | ||
70 | /// <summary> | ||
71 | /// If true then we ask the viewer to disable teleport cancellation and ignore teleport requests. | ||
72 | /// </summary> | ||
73 | /// <remarks> | ||
74 | /// This is useful in situations where teleport is very likely to always succeed and we want to avoid a | ||
75 | /// situation where avatars can be come 'stuck' due to a failed teleport cancellation. Unfortunately, the | ||
76 | /// nature of the teleport protocol makes it extremely difficult (maybe impossible) to make teleport | ||
77 | /// cancellation consistently suceed. | ||
78 | /// </remarks> | ||
79 | public bool DisableInterRegionTeleportCancellation { get; set; } | ||
80 | |||
81 | /// <summary> | ||
82 | /// Number of times inter-region teleport was attempted. | ||
83 | /// </summary> | ||
84 | private Stat m_interRegionTeleportAttempts; | ||
85 | |||
86 | /// <summary> | ||
87 | /// Number of times inter-region teleport was aborted (due to simultaneous client logout). | ||
88 | /// </summary> | ||
89 | private Stat m_interRegionTeleportAborts; | ||
90 | |||
91 | /// <summary> | ||
92 | /// Number of times inter-region teleport was successfully cancelled by the client. | ||
93 | /// </summary> | ||
94 | private Stat m_interRegionTeleportCancels; | ||
95 | |||
96 | /// <summary> | ||
97 | /// Number of times inter-region teleport failed due to server/client/network problems (e.g. viewer failed to | ||
98 | /// connect with destination region). | ||
99 | /// </summary> | ||
100 | /// <remarks> | ||
101 | /// This is not necessarily a problem for this simulator - in open-grid/hg conditions, viewer connectivity to | ||
102 | /// destination simulator is unknown. | ||
103 | /// </remarks> | ||
104 | private Stat m_interRegionTeleportFailures; | ||
105 | |||
69 | protected bool m_Enabled = false; | 106 | protected bool m_Enabled = false; |
70 | 107 | ||
71 | public Scene Scene { get; private set; } | 108 | public Scene Scene { get; private set; } |
@@ -80,6 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
80 | new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); | 117 | new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); |
81 | 118 | ||
82 | private IEventQueue m_eqModule; | 119 | private IEventQueue m_eqModule; |
120 | private IRegionCombinerModule m_regionCombinerModule; | ||
83 | 121 | ||
84 | #region ISharedRegionModule | 122 | #region ISharedRegionModule |
85 | 123 | ||
@@ -116,6 +154,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
116 | IConfig transferConfig = source.Configs["EntityTransfer"]; | 154 | IConfig transferConfig = source.Configs["EntityTransfer"]; |
117 | if (transferConfig != null) | 155 | if (transferConfig != null) |
118 | { | 156 | { |
157 | DisableInterRegionTeleportCancellation | ||
158 | = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); | ||
159 | |||
119 | WaitForAgentArrivedAtDestination | 160 | WaitForAgentArrivedAtDestination |
120 | = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); | 161 | = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); |
121 | 162 | ||
@@ -142,6 +183,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
142 | 183 | ||
143 | Scene = scene; | 184 | Scene = scene; |
144 | 185 | ||
186 | m_interRegionTeleportAttempts = | ||
187 | new Stat( | ||
188 | "InterRegionTeleportAttempts", | ||
189 | "Number of inter-region teleports attempted.", | ||
190 | "This does not count attempts which failed due to pre-conditions (e.g. target simulator refused access).\n" | ||
191 | + "You can get successfully teleports by subtracting aborts, cancels and teleport failures from this figure.", | ||
192 | "", | ||
193 | "entitytransfer", | ||
194 | Scene.Name, | ||
195 | StatType.Push, | ||
196 | null, | ||
197 | StatVerbosity.Debug); | ||
198 | |||
199 | m_interRegionTeleportAborts = | ||
200 | new Stat( | ||
201 | "InterRegionTeleportAborts", | ||
202 | "Number of inter-region teleports aborted due to client actions.", | ||
203 | "The chief action is simultaneous logout whilst teleporting.", | ||
204 | "", | ||
205 | "entitytransfer", | ||
206 | Scene.Name, | ||
207 | StatType.Push, | ||
208 | null, | ||
209 | StatVerbosity.Debug); | ||
210 | |||
211 | m_interRegionTeleportCancels = | ||
212 | new Stat( | ||
213 | "InterRegionTeleportCancels", | ||
214 | "Number of inter-region teleports cancelled by the client.", | ||
215 | null, | ||
216 | "", | ||
217 | "entitytransfer", | ||
218 | Scene.Name, | ||
219 | StatType.Push, | ||
220 | null, | ||
221 | StatVerbosity.Debug); | ||
222 | |||
223 | m_interRegionTeleportFailures = | ||
224 | new Stat( | ||
225 | "InterRegionTeleportFailures", | ||
226 | "Number of inter-region teleports that failed due to server/client/network issues.", | ||
227 | "This number may not be very helpful in open-grid/hg situations as the network connectivity/quality of destinations is uncontrollable.", | ||
228 | "", | ||
229 | "entitytransfer", | ||
230 | Scene.Name, | ||
231 | StatType.Push, | ||
232 | null, | ||
233 | StatVerbosity.Debug); | ||
234 | |||
235 | StatsManager.RegisterStat(m_interRegionTeleportAttempts); | ||
236 | StatsManager.RegisterStat(m_interRegionTeleportAborts); | ||
237 | StatsManager.RegisterStat(m_interRegionTeleportCancels); | ||
238 | StatsManager.RegisterStat(m_interRegionTeleportFailures); | ||
239 | |||
145 | scene.RegisterModuleInterface<IEntityTransferModule>(this); | 240 | scene.RegisterModuleInterface<IEntityTransferModule>(this); |
146 | scene.EventManager.OnNewClient += OnNewClient; | 241 | scene.EventManager.OnNewClient += OnNewClient; |
147 | } | 242 | } |
@@ -150,12 +245,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
150 | { | 245 | { |
151 | client.OnTeleportHomeRequest += TriggerTeleportHome; | 246 | client.OnTeleportHomeRequest += TriggerTeleportHome; |
152 | client.OnTeleportLandmarkRequest += RequestTeleportLandmark; | 247 | client.OnTeleportLandmarkRequest += RequestTeleportLandmark; |
153 | client.OnTeleportCancel += TeleportCancel; | 248 | |
249 | if (!DisableInterRegionTeleportCancellation) | ||
250 | client.OnTeleportCancel += OnClientCancelTeleport; | ||
251 | |||
252 | client.OnConnectionClosed += OnConnectionClosed; | ||
154 | } | 253 | } |
155 | 254 | ||
156 | public virtual void Close() {} | 255 | public virtual void Close() {} |
157 | 256 | ||
158 | public virtual void RemoveRegion(Scene scene) {} | 257 | public virtual void RemoveRegion(Scene scene) |
258 | { | ||
259 | if (m_Enabled) | ||
260 | { | ||
261 | StatsManager.DeregisterStat(m_interRegionTeleportAttempts); | ||
262 | StatsManager.DeregisterStat(m_interRegionTeleportAborts); | ||
263 | StatsManager.DeregisterStat(m_interRegionTeleportCancels); | ||
264 | StatsManager.DeregisterStat(m_interRegionTeleportFailures); | ||
265 | } | ||
266 | } | ||
159 | 267 | ||
160 | public virtual void RegionLoaded(Scene scene) | 268 | public virtual void RegionLoaded(Scene scene) |
161 | { | 269 | { |
@@ -163,12 +271,33 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
163 | return; | 271 | return; |
164 | 272 | ||
165 | m_eqModule = Scene.RequestModuleInterface<IEventQueue>(); | 273 | m_eqModule = Scene.RequestModuleInterface<IEventQueue>(); |
274 | m_regionCombinerModule = Scene.RequestModuleInterface<IRegionCombinerModule>(); | ||
166 | } | 275 | } |
167 | 276 | ||
168 | #endregion | 277 | #endregion |
169 | 278 | ||
170 | #region Agent Teleports | 279 | #region Agent Teleports |
171 | 280 | ||
281 | private void OnConnectionClosed(IClientAPI client) | ||
282 | { | ||
283 | if (client.IsLoggingOut) | ||
284 | { | ||
285 | m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting); | ||
286 | |||
287 | m_log.DebugFormat( | ||
288 | "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout", | ||
289 | client.Name, Scene.Name); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | private void OnClientCancelTeleport(IClientAPI client) | ||
294 | { | ||
295 | m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling); | ||
296 | |||
297 | m_log.DebugFormat( | ||
298 | "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name); | ||
299 | } | ||
300 | |||
172 | public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) | 301 | public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) |
173 | { | 302 | { |
174 | if (sp.Scene.Permissions.IsGridGod(sp.UUID)) | 303 | if (sp.Scene.Permissions.IsGridGod(sp.UUID)) |
@@ -180,13 +309,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
180 | if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) | 309 | if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) |
181 | return; | 310 | return; |
182 | 311 | ||
183 | // Reset animations; the viewer does that in teleports. | ||
184 | sp.Animator.ResetAnimations(); | ||
185 | |||
186 | string destinationRegionName = "(not found)"; | 312 | string destinationRegionName = "(not found)"; |
187 | 313 | ||
314 | // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection | ||
315 | // of whether the destination region completes the teleport. | ||
316 | if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) | ||
317 | { | ||
318 | m_log.DebugFormat( | ||
319 | "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.", | ||
320 | sp.Name, sp.UUID, position, regionHandle); | ||
321 | |||
322 | return; | ||
323 | } | ||
324 | |||
188 | try | 325 | try |
189 | { | 326 | { |
327 | // Reset animations; the viewer does that in teleports. | ||
328 | sp.Animator.ResetAnimations(); | ||
329 | |||
190 | if (regionHandle == sp.Scene.RegionInfo.RegionHandle) | 330 | if (regionHandle == sp.Scene.RegionInfo.RegionHandle) |
191 | { | 331 | { |
192 | destinationRegionName = sp.Scene.RegionInfo.RegionName; | 332 | destinationRegionName = sp.Scene.RegionInfo.RegionName; |
@@ -195,12 +335,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
195 | } | 335 | } |
196 | else // Another region possibly in another simulator | 336 | else // Another region possibly in another simulator |
197 | { | 337 | { |
198 | GridRegion finalDestination; | 338 | GridRegion finalDestination = null; |
199 | TeleportAgentToDifferentRegion( | 339 | try |
200 | sp, regionHandle, position, lookAt, teleportFlags, out finalDestination); | 340 | { |
201 | 341 | TeleportAgentToDifferentRegion( | |
202 | if (finalDestination != null) | 342 | sp, regionHandle, position, lookAt, teleportFlags, out finalDestination); |
203 | destinationRegionName = finalDestination.RegionName; | 343 | } |
344 | finally | ||
345 | { | ||
346 | if (finalDestination != null) | ||
347 | destinationRegionName = finalDestination.RegionName; | ||
348 | } | ||
204 | } | 349 | } |
205 | } | 350 | } |
206 | catch (Exception e) | 351 | catch (Exception e) |
@@ -210,11 +355,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
210 | sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, | 355 | sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, |
211 | e.Message, e.StackTrace); | 356 | e.Message, e.StackTrace); |
212 | 357 | ||
213 | // Make sure that we clear the in-transit flag so that future teleport attempts don't always fail. | ||
214 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
215 | |||
216 | sp.ControllingClient.SendTeleportFailed("Internal error"); | 358 | sp.ControllingClient.SendTeleportFailed("Internal error"); |
217 | } | 359 | } |
360 | finally | ||
361 | { | ||
362 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
363 | } | ||
218 | } | 364 | } |
219 | 365 | ||
220 | /// <summary> | 366 | /// <summary> |
@@ -230,23 +376,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
230 | "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}", | 376 | "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}", |
231 | sp.Name, position, sp.Scene.RegionInfo.RegionName); | 377 | sp.Name, position, sp.Scene.RegionInfo.RegionName); |
232 | 378 | ||
233 | if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) | ||
234 | { | ||
235 | m_log.DebugFormat( | ||
236 | "[ENTITY TRANSFER MODULE]: Ignoring within region teleport request of {0} {1} to {2} - agent is already in transit.", | ||
237 | sp.Name, sp.UUID, position); | ||
238 | |||
239 | return; | ||
240 | } | ||
241 | |||
242 | // Teleport within the same region | 379 | // Teleport within the same region |
243 | if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) | 380 | if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) |
244 | { | 381 | { |
245 | Vector3 emergencyPos = new Vector3(128, 128, 128); | 382 | Vector3 emergencyPos = new Vector3(128, 128, 128); |
246 | 383 | ||
247 | m_log.WarnFormat( | 384 | m_log.WarnFormat( |
248 | "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", | 385 | "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2} in {3}. Substituting {4}", |
249 | position, sp.Name, sp.UUID, emergencyPos); | 386 | position, sp.Name, sp.UUID, Scene.Name, emergencyPos); |
250 | 387 | ||
251 | position = emergencyPos; | 388 | position = emergencyPos; |
252 | } | 389 | } |
@@ -287,7 +424,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
287 | } | 424 | } |
288 | 425 | ||
289 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 426 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
290 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
291 | } | 427 | } |
292 | 428 | ||
293 | /// <summary> | 429 | /// <summary> |
@@ -341,7 +477,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
341 | // | 477 | // |
342 | // This is it | 478 | // This is it |
343 | // | 479 | // |
344 | DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags); | 480 | DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags); |
345 | // | 481 | // |
346 | // | 482 | // |
347 | // | 483 | // |
@@ -396,27 +532,54 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
396 | && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance; | 532 | && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance; |
397 | } | 533 | } |
398 | 534 | ||
535 | /// <summary> | ||
536 | /// Wraps DoTeleportInternal() and manages the transfer state. | ||
537 | /// </summary> | ||
399 | public void DoTeleport( | 538 | public void DoTeleport( |
400 | ScenePresence sp, GridRegion reg, GridRegion finalDestination, | 539 | ScenePresence sp, GridRegion reg, GridRegion finalDestination, |
401 | Vector3 position, Vector3 lookAt, uint teleportFlags) | 540 | Vector3 position, Vector3 lookAt, uint teleportFlags) |
402 | { | 541 | { |
403 | // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection | 542 | // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection |
404 | // of whether the destination region completes the teleport. | 543 | // of whether the destination region completes the teleport. |
405 | m_entityTransferStateMachine.SetInTransit(sp.UUID); | 544 | if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) |
406 | // if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) | 545 | { |
407 | // { | 546 | m_log.DebugFormat( |
408 | // m_log.DebugFormat( | 547 | "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", |
409 | // "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", | 548 | sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); |
410 | // sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); | ||
411 | // | ||
412 | // return; | ||
413 | // } | ||
414 | 549 | ||
415 | if (reg == null || finalDestination == null) | 550 | return; |
551 | } | ||
552 | |||
553 | try | ||
554 | { | ||
555 | DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags); | ||
556 | } | ||
557 | catch (Exception e) | ||
558 | { | ||
559 | m_log.ErrorFormat( | ||
560 | "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}", | ||
561 | sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, finalDestination.RegionName, | ||
562 | e.Message, e.StackTrace); | ||
563 | |||
564 | sp.ControllingClient.SendTeleportFailed("Internal error"); | ||
565 | } | ||
566 | finally | ||
416 | { | 567 | { |
417 | sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); | ||
418 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | 568 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); |
569 | } | ||
570 | } | ||
419 | 571 | ||
572 | /// <summary> | ||
573 | /// Teleports the agent to another region. | ||
574 | /// This method doesn't manage the transfer state; the caller must do that. | ||
575 | /// </summary> | ||
576 | private void DoTeleportInternal( | ||
577 | ScenePresence sp, GridRegion reg, GridRegion finalDestination, | ||
578 | Vector3 position, Vector3 lookAt, uint teleportFlags) | ||
579 | { | ||
580 | if (reg == null || finalDestination == null) | ||
581 | { | ||
582 | sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); | ||
420 | return; | 583 | return; |
421 | } | 584 | } |
422 | 585 | ||
@@ -436,8 +599,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
436 | sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, | 599 | sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, |
437 | MaxTransferDistance)); | 600 | MaxTransferDistance)); |
438 | 601 | ||
439 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
440 | |||
441 | return; | 602 | return; |
442 | } | 603 | } |
443 | 604 | ||
@@ -455,7 +616,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
455 | if (endPoint == null || endPoint.Address == null) | 616 | if (endPoint == null || endPoint.Address == null) |
456 | { | 617 | { |
457 | sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); | 618 | sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); |
458 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
459 | 619 | ||
460 | return; | 620 | return; |
461 | } | 621 | } |
@@ -465,19 +625,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
465 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", | 625 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", |
466 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); | 626 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); |
467 | 627 | ||
468 | // if (!sp.ValidateAttachments()) | ||
469 | // { | ||
470 | // sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); | ||
471 | // return; | ||
472 | // } | ||
473 | |||
474 | string reason; | 628 | string reason; |
475 | string version; | 629 | string version; |
476 | if (!Scene.SimulationService.QueryAccess( | 630 | if (!Scene.SimulationService.QueryAccess( |
477 | finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) | 631 | finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) |
478 | { | 632 | { |
479 | sp.ControllingClient.SendTeleportFailed(reason); | 633 | sp.ControllingClient.SendTeleportFailed(reason); |
480 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
481 | 634 | ||
482 | m_log.DebugFormat( | 635 | m_log.DebugFormat( |
483 | "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", | 636 | "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", |
@@ -486,6 +639,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
486 | return; | 639 | return; |
487 | } | 640 | } |
488 | 641 | ||
642 | // Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target | ||
643 | // simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these | ||
644 | // as server attempts. | ||
645 | m_interRegionTeleportAttempts.Value++; | ||
646 | |||
489 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); | 647 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); |
490 | 648 | ||
491 | // Fixing a bug where teleporting while sitting results in the avatar ending up removed from | 649 | // Fixing a bug where teleporting while sitting results in the avatar ending up removed from |
@@ -495,6 +653,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
495 | else if (sp.Flying) | 653 | else if (sp.Flying) |
496 | teleportFlags |= (uint)TeleportFlags.IsFlying; | 654 | teleportFlags |= (uint)TeleportFlags.IsFlying; |
497 | 655 | ||
656 | if (DisableInterRegionTeleportCancellation) | ||
657 | teleportFlags |= (uint)TeleportFlags.DisableCancel; | ||
658 | |||
498 | // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to | 659 | // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to |
499 | // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). | 660 | // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). |
500 | sp.ControllingClient.SendTeleportStart(teleportFlags); | 661 | sp.ControllingClient.SendTeleportStart(teleportFlags); |
@@ -531,11 +692,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
531 | } | 692 | } |
532 | 693 | ||
533 | // Let's create an agent there if one doesn't exist yet. | 694 | // Let's create an agent there if one doesn't exist yet. |
695 | // NOTE: logout will always be false for a non-HG teleport. | ||
534 | bool logout = false; | 696 | bool logout = false; |
535 | if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) | 697 | if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) |
536 | { | 698 | { |
699 | m_interRegionTeleportFailures.Value++; | ||
700 | |||
537 | sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); | 701 | sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); |
538 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
539 | 702 | ||
540 | m_log.DebugFormat( | 703 | m_log.DebugFormat( |
541 | "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", | 704 | "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", |
@@ -544,6 +707,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
544 | return; | 707 | return; |
545 | } | 708 | } |
546 | 709 | ||
710 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) | ||
711 | { | ||
712 | m_interRegionTeleportCancels.Value++; | ||
713 | |||
714 | m_log.DebugFormat( | ||
715 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", | ||
716 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
717 | |||
718 | return; | ||
719 | } | ||
720 | else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
721 | { | ||
722 | m_interRegionTeleportAborts.Value++; | ||
723 | |||
724 | m_log.DebugFormat( | ||
725 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", | ||
726 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
727 | |||
728 | return; | ||
729 | } | ||
730 | |||
547 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. | 731 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. |
548 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); | 732 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); |
549 | 733 | ||
@@ -553,6 +737,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
553 | IClientIPEndpoint ipepClient; | 737 | IClientIPEndpoint ipepClient; |
554 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) | 738 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) |
555 | { | 739 | { |
740 | m_log.DebugFormat( | ||
741 | "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", | ||
742 | finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name); | ||
743 | |||
556 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); | 744 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); |
557 | #region IP Translation for NAT | 745 | #region IP Translation for NAT |
558 | // Uses ipepClient above | 746 | // Uses ipepClient above |
@@ -565,11 +753,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
565 | 753 | ||
566 | if (m_eqModule != null) | 754 | if (m_eqModule != null) |
567 | { | 755 | { |
756 | // The EnableSimulator message makes the client establish a connection with the destination | ||
757 | // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the | ||
758 | // correct circuit code. | ||
568 | m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); | 759 | m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); |
569 | 760 | ||
570 | // ES makes the client send a UseCircuitCode message to the destination, | 761 | // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination |
571 | // which triggers a bunch of things there. | 762 | // simulator to confirm that it has established communication with the viewer. |
572 | // So let's wait | ||
573 | Thread.Sleep(200); | 763 | Thread.Sleep(200); |
574 | 764 | ||
575 | // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears | 765 | // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears |
@@ -580,6 +770,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
580 | } | 770 | } |
581 | else | 771 | else |
582 | { | 772 | { |
773 | // XXX: This is a little misleading since we're information the client of its avatar destination, | ||
774 | // which may or may not be a neighbour region of the source region. This path is probably little | ||
775 | // used anyway (with EQ being the one used). But it is currently being used for test code. | ||
583 | sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); | 776 | sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); |
584 | } | 777 | } |
585 | } | 778 | } |
@@ -597,23 +790,66 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
597 | 790 | ||
598 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); | 791 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); |
599 | 792 | ||
793 | // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to | ||
794 | // establish th econnection to the destination which makes it return true. | ||
795 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
796 | { | ||
797 | m_interRegionTeleportAborts.Value++; | ||
798 | |||
799 | m_log.DebugFormat( | ||
800 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent", | ||
801 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
802 | |||
803 | return; | ||
804 | } | ||
805 | |||
806 | // A common teleport failure occurs when we can send CreateAgent to the | ||
807 | // destination region but the viewer cannot establish the connection (e.g. due to network issues between | ||
808 | // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then | ||
809 | // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). | ||
600 | if (!UpdateAgent(reg, finalDestination, agent, sp)) | 810 | if (!UpdateAgent(reg, finalDestination, agent, sp)) |
601 | { | 811 | { |
602 | // Region doesn't take it | 812 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) |
813 | { | ||
814 | m_interRegionTeleportAborts.Value++; | ||
815 | |||
816 | m_log.DebugFormat( | ||
817 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", | ||
818 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
819 | |||
820 | return; | ||
821 | } | ||
822 | |||
603 | m_log.WarnFormat( | 823 | m_log.WarnFormat( |
604 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Returning avatar to source region.", | 824 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", |
605 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 825 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
606 | 826 | ||
607 | Fail(sp, finalDestination, logout); | 827 | Fail(sp, finalDestination, logout, "Connection between viewer and destination region could not be established."); |
608 | return; | 828 | return; |
609 | } | 829 | } |
610 | 830 | ||
611 | sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest"); | 831 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) |
832 | { | ||
833 | m_interRegionTeleportCancels.Value++; | ||
834 | |||
835 | m_log.DebugFormat( | ||
836 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", | ||
837 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
838 | |||
839 | CleanupFailedInterRegionTeleport(sp, finalDestination); | ||
840 | |||
841 | return; | ||
842 | } | ||
612 | 843 | ||
613 | m_log.DebugFormat( | 844 | m_log.DebugFormat( |
614 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", | 845 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", |
615 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); | 846 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); |
616 | 847 | ||
848 | // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, | ||
849 | // where that neighbour simulator could otherwise request a child agent create on the source which then | ||
850 | // closes our existing agent which is still signalled as root. | ||
851 | sp.IsChildAgent = true; | ||
852 | |||
617 | if (m_eqModule != null) | 853 | if (m_eqModule != null) |
618 | { | 854 | { |
619 | m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); | 855 | m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); |
@@ -624,19 +860,28 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
624 | teleportFlags, capsPath); | 860 | teleportFlags, capsPath); |
625 | } | 861 | } |
626 | 862 | ||
627 | // Let's set this to true tentatively. This does not trigger OnChildAgent | ||
628 | sp.IsChildAgent = true; | ||
629 | |||
630 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which | 863 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which |
631 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation | 864 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation |
632 | // that the client contacted the destination before we close things here. | 865 | // that the client contacted the destination before we close things here. |
633 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) | 866 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) |
634 | { | 867 | { |
868 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
869 | { | ||
870 | m_interRegionTeleportAborts.Value++; | ||
871 | |||
872 | m_log.DebugFormat( | ||
873 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", | ||
874 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
875 | |||
876 | return; | ||
877 | } | ||
878 | |||
635 | m_log.WarnFormat( | 879 | m_log.WarnFormat( |
636 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", | 880 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", |
637 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 881 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
638 | 882 | ||
639 | Fail(sp, finalDestination, logout); | 883 | Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion."); |
884 | |||
640 | return; | 885 | return; |
641 | } | 886 | } |
642 | 887 | ||
@@ -659,8 +904,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
659 | // Now let's make it officially a child agent | 904 | // Now let's make it officially a child agent |
660 | sp.MakeChildAgent(); | 905 | sp.MakeChildAgent(); |
661 | 906 | ||
662 | // sp.Scene.CleanDroppedAttachments(); | ||
663 | |||
664 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone | 907 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone |
665 | 908 | ||
666 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) | 909 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) |
@@ -680,27 +923,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
680 | // now we have a child agent in this region. | 923 | // now we have a child agent in this region. |
681 | sp.Reset(); | 924 | sp.Reset(); |
682 | } | 925 | } |
683 | |||
684 | // Commented pending deletion since this method no longer appears to do anything at all | ||
685 | // // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | ||
686 | // if (sp.Scene.NeedSceneCacheClear(sp.UUID)) | ||
687 | // { | ||
688 | // m_log.DebugFormat( | ||
689 | // "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", | ||
690 | // sp.UUID); | ||
691 | // } | ||
692 | |||
693 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
694 | } | 926 | } |
695 | 927 | ||
696 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout) | 928 | /// <summary> |
929 | /// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation. | ||
930 | /// </summary> | ||
931 | /// <remarks> | ||
932 | /// All operations here must be idempotent so that we can call this method at any point in the teleport process | ||
933 | /// up until we send the TeleportFinish event quene event to the viewer. | ||
934 | /// <remarks> | ||
935 | /// <param name='sp'> </param> | ||
936 | /// <param name='finalDestination'></param> | ||
937 | protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) | ||
697 | { | 938 | { |
698 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 939 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
699 | 940 | ||
700 | // Client never contacted destination. Let's restore everything back | ||
701 | sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); | ||
702 | |||
703 | // Fail. Reset it back | ||
704 | sp.IsChildAgent = false; | 941 | sp.IsChildAgent = false; |
705 | ReInstantiateScripts(sp); | 942 | ReInstantiateScripts(sp); |
706 | 943 | ||
@@ -708,10 +945,26 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
708 | 945 | ||
709 | // Finally, kill the agent we just created at the destination. | 946 | // Finally, kill the agent we just created at the destination. |
710 | Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); | 947 | Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); |
948 | } | ||
711 | 949 | ||
712 | sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); | 950 | /// <summary> |
951 | /// Signal that the inter-region teleport failed and perform cleanup. | ||
952 | /// </summary> | ||
953 | /// <param name='sp'></param> | ||
954 | /// <param name='finalDestination'></param> | ||
955 | /// <param name='logout'></param> | ||
956 | /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> | ||
957 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) | ||
958 | { | ||
959 | CleanupFailedInterRegionTeleport(sp, finalDestination); | ||
960 | |||
961 | m_interRegionTeleportFailures.Value++; | ||
713 | 962 | ||
714 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | 963 | sp.ControllingClient.SendTeleportFailed( |
964 | string.Format( | ||
965 | "Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason)); | ||
966 | |||
967 | sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); | ||
715 | } | 968 | } |
716 | 969 | ||
717 | protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) | 970 | protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) |
@@ -762,7 +1015,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
762 | 1015 | ||
763 | protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) | 1016 | protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) |
764 | { | 1017 | { |
765 | return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); | 1018 | if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) |
1019 | { | ||
1020 | Vector2 swCorner, neCorner; | ||
1021 | GetMegaregionViewRange(out swCorner, out neCorner); | ||
1022 | |||
1023 | m_log.DebugFormat( | ||
1024 | "[ENTITY TRANSFER MODULE]: Megaregion view of {0} is from {1} to {2} with new agent check for {3},{4}", | ||
1025 | Scene.Name, swCorner, neCorner, newRegionX, newRegionY); | ||
1026 | |||
1027 | return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y); | ||
1028 | } | ||
1029 | else | ||
1030 | { | ||
1031 | return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); | ||
1032 | } | ||
766 | } | 1033 | } |
767 | 1034 | ||
768 | protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) | 1035 | protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) |
@@ -866,6 +1133,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
866 | { | 1133 | { |
867 | version = String.Empty; | 1134 | version = String.Empty; |
868 | newpos = new Vector3(pos.X, pos.Y, pos.Z); | 1135 | newpos = new Vector3(pos.X, pos.Y, pos.Z); |
1136 | |||
1137 | // m_log.DebugFormat( | ||
1138 | // "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); | ||
1139 | |||
869 | uint neighbourx = scene.RegionInfo.RegionLocX; | 1140 | uint neighbourx = scene.RegionInfo.RegionLocX; |
870 | uint neighboury = scene.RegionInfo.RegionLocY; | 1141 | uint neighboury = scene.RegionInfo.RegionLocY; |
871 | const float boundaryDistance = 1.7f; | 1142 | const float boundaryDistance = 1.7f; |
@@ -995,11 +1266,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
995 | return neighbourRegion; | 1266 | return neighbourRegion; |
996 | } | 1267 | } |
997 | 1268 | ||
998 | private void TeleportCancel(IClientAPI remoteClient) | ||
999 | { | ||
1000 | m_entityTransferStateMachine.ResetFromTransit(remoteClient.AgentId); | ||
1001 | } | ||
1002 | |||
1003 | public bool Cross(ScenePresence agent, bool isFlying) | 1269 | public bool Cross(ScenePresence agent, bool isFlying) |
1004 | { | 1270 | { |
1005 | uint x; | 1271 | uint x; |
@@ -1023,16 +1289,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1023 | } | 1289 | } |
1024 | 1290 | ||
1025 | 1291 | ||
1026 | public delegate void InformClientToInitateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, | 1292 | public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, |
1027 | Vector3 position, | 1293 | Vector3 position, |
1028 | Scene initiatingScene); | 1294 | Scene initiatingScene); |
1029 | 1295 | ||
1030 | private void InformClientToInitateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) | 1296 | private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) |
1031 | { | 1297 | { |
1032 | 1298 | ||
1033 | // This assumes that we know what our neighbours are. | 1299 | // This assumes that we know what our neighbours are. |
1034 | 1300 | ||
1035 | InformClientToInitateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync; | 1301 | InformClientToInitiateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync; |
1036 | d.BeginInvoke(agent, regionX, regionY, position, initiatingScene, | 1302 | d.BeginInvoke(agent, regionX, regionY, position, initiatingScene, |
1037 | InformClientToInitiateTeleportToLocationCompleted, | 1303 | InformClientToInitiateTeleportToLocationCompleted, |
1038 | d); | 1304 | d); |
@@ -1042,7 +1308,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1042 | Scene initiatingScene) | 1308 | Scene initiatingScene) |
1043 | { | 1309 | { |
1044 | Thread.Sleep(10000); | 1310 | Thread.Sleep(10000); |
1045 | 1311 | ||
1312 | m_log.DebugFormat( | ||
1313 | "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}", | ||
1314 | agent.Name, regionX, regionY, position, initiatingScene.Name); | ||
1315 | |||
1316 | agent.Scene.RequestTeleportLocation( | ||
1317 | agent.ControllingClient, | ||
1318 | Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize), | ||
1319 | position, | ||
1320 | agent.Lookat, | ||
1321 | (uint)Constants.TeleportFlags.ViaLocation); | ||
1322 | |||
1323 | /* | ||
1046 | IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); | 1324 | IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); |
1047 | if (im != null) | 1325 | if (im != null) |
1048 | { | 1326 | { |
@@ -1077,12 +1355,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1077 | }); | 1355 | }); |
1078 | 1356 | ||
1079 | } | 1357 | } |
1358 | */ | ||
1080 | } | 1359 | } |
1081 | 1360 | ||
1082 | private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar) | 1361 | private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar) |
1083 | { | 1362 | { |
1084 | InformClientToInitateTeleportToLocationDelegate icon = | 1363 | InformClientToInitiateTeleportToLocationDelegate icon = |
1085 | (InformClientToInitateTeleportToLocationDelegate)iar.AsyncState; | 1364 | (InformClientToInitiateTeleportToLocationDelegate)iar.AsyncState; |
1086 | icon.EndInvoke(iar); | 1365 | icon.EndInvoke(iar); |
1087 | } | 1366 | } |
1088 | 1367 | ||
@@ -1107,10 +1386,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1107 | bool isFlying, string version) | 1386 | bool isFlying, string version) |
1108 | { | 1387 | { |
1109 | if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) | 1388 | if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) |
1389 | { | ||
1390 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1110 | return agent; | 1391 | return agent; |
1392 | } | ||
1111 | 1393 | ||
1112 | if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) | 1394 | if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) |
1395 | { | ||
1396 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1113 | return agent; | 1397 | return agent; |
1398 | } | ||
1114 | 1399 | ||
1115 | CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); | 1400 | CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); |
1116 | return agent; | 1401 | return agent; |
@@ -1137,9 +1422,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1137 | // region doesn't take it | 1422 | // region doesn't take it |
1138 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); | 1423 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); |
1139 | 1424 | ||
1425 | m_log.WarnFormat( | ||
1426 | "[ENTITY TRANSFER MODULE]: Region {0} would not accept update for agent {1} on cross attempt. Returning to original region.", | ||
1427 | neighbourRegion.RegionName, agent.Name); | ||
1428 | |||
1140 | ReInstantiateScripts(agent); | 1429 | ReInstantiateScripts(agent); |
1141 | agent.AddToPhysicalScene(isFlying); | 1430 | agent.AddToPhysicalScene(isFlying); |
1142 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1143 | 1431 | ||
1144 | return false; | 1432 | return false; |
1145 | } | 1433 | } |
@@ -1576,6 +1864,37 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1576 | } | 1864 | } |
1577 | 1865 | ||
1578 | /// <summary> | 1866 | /// <summary> |
1867 | /// Gets the range considered in view of this megaregion (assuming this is a megaregion). | ||
1868 | /// </summary> | ||
1869 | /// <remarks>Expressed in 256m units</remarks> | ||
1870 | /// <param name='swCorner'></param> | ||
1871 | /// <param name='neCorner'></param> | ||
1872 | private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner) | ||
1873 | { | ||
1874 | Border[] northBorders = Scene.NorthBorders.ToArray(); | ||
1875 | Border[] eastBorders = Scene.EastBorders.ToArray(); | ||
1876 | |||
1877 | Vector2 extent = Vector2.Zero; | ||
1878 | for (int i = 0; i < eastBorders.Length; i++) | ||
1879 | { | ||
1880 | extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X; | ||
1881 | } | ||
1882 | for (int i = 0; i < northBorders.Length; i++) | ||
1883 | { | ||
1884 | extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y; | ||
1885 | } | ||
1886 | |||
1887 | // Loss of fraction on purpose | ||
1888 | extent.X = ((int)extent.X / (int)Constants.RegionSize); | ||
1889 | extent.Y = ((int)extent.Y / (int)Constants.RegionSize); | ||
1890 | |||
1891 | swCorner.X = Scene.RegionInfo.RegionLocX - 1; | ||
1892 | swCorner.Y = Scene.RegionInfo.RegionLocY - 1; | ||
1893 | neCorner.X = Scene.RegionInfo.RegionLocX + extent.X; | ||
1894 | neCorner.Y = Scene.RegionInfo.RegionLocY + extent.Y; | ||
1895 | } | ||
1896 | |||
1897 | /// <summary> | ||
1579 | /// Return the list of regions that are considered to be neighbours to the given scene. | 1898 | /// Return the list of regions that are considered to be neighbours to the given scene. |
1580 | /// </summary> | 1899 | /// </summary> |
1581 | /// <param name="pScene"></param> | 1900 | /// <param name="pScene"></param> |
@@ -1587,15 +1906,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1587 | Scene pScene = avatar.Scene; | 1906 | Scene pScene = avatar.Scene; |
1588 | RegionInfo m_regionInfo = pScene.RegionInfo; | 1907 | RegionInfo m_regionInfo = pScene.RegionInfo; |
1589 | 1908 | ||
1590 | Border[] northBorders = pScene.NorthBorders.ToArray(); | ||
1591 | Border[] southBorders = pScene.SouthBorders.ToArray(); | ||
1592 | Border[] eastBorders = pScene.EastBorders.ToArray(); | ||
1593 | Border[] westBorders = pScene.WestBorders.ToArray(); | ||
1594 | |||
1595 | // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't | 1909 | // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't |
1596 | // clear what should be done with a "far view" given that megaregions already extended the | 1910 | // clear what should be done with a "far view" given that megaregions already extended the |
1597 | // view to include everything in the megaregion | 1911 | // view to include everything in the megaregion |
1598 | if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1) | 1912 | if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) |
1599 | { | 1913 | { |
1600 | int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; | 1914 | int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; |
1601 | 1915 | ||
@@ -1613,27 +1927,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1613 | } | 1927 | } |
1614 | else | 1928 | else |
1615 | { | 1929 | { |
1616 | Vector2 extent = Vector2.Zero; | 1930 | Vector2 swCorner, neCorner; |
1617 | for (int i = 0; i < eastBorders.Length; i++) | 1931 | GetMegaregionViewRange(out swCorner, out neCorner); |
1618 | { | ||
1619 | extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X; | ||
1620 | } | ||
1621 | for (int i = 0; i < northBorders.Length; i++) | ||
1622 | { | ||
1623 | extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y; | ||
1624 | } | ||
1625 | |||
1626 | // Loss of fraction on purpose | ||
1627 | extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1; | ||
1628 | extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1; | ||
1629 | |||
1630 | int startX = (int)(pRegionLocX - 1) * (int)Constants.RegionSize; | ||
1631 | int startY = (int)(pRegionLocY - 1) * (int)Constants.RegionSize; | ||
1632 | 1932 | ||
1633 | int endX = ((int)pRegionLocX + (int)extent.X) * (int)Constants.RegionSize; | 1933 | List<GridRegion> neighbours |
1634 | int endY = ((int)pRegionLocY + (int)extent.Y) * (int)Constants.RegionSize; | 1934 | = pScene.GridService.GetRegionRange( |
1935 | m_regionInfo.ScopeID, | ||
1936 | (int)swCorner.X * (int)Constants.RegionSize, | ||
1937 | (int)neCorner.X * (int)Constants.RegionSize, | ||
1938 | (int)swCorner.Y * (int)Constants.RegionSize, | ||
1939 | (int)neCorner.Y * (int)Constants.RegionSize); | ||
1635 | 1940 | ||
1636 | List<GridRegion> neighbours = pScene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY); | ||
1637 | neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); | 1941 | neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); |
1638 | 1942 | ||
1639 | return neighbours; | 1943 | return neighbours; |
@@ -2054,7 +2358,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2054 | 2358 | ||
2055 | public bool IsInTransit(UUID id) | 2359 | public bool IsInTransit(UUID id) |
2056 | { | 2360 | { |
2057 | return m_entityTransferStateMachine.IsInTransit(id); | 2361 | return m_entityTransferStateMachine.GetAgentTransferState(id) != null; |
2058 | } | 2362 | } |
2059 | 2363 | ||
2060 | protected void ReInstantiateScripts(ScenePresence sp) | 2364 | protected void ReInstantiateScripts(ScenePresence sp) |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs index 70dd1bc..e903383 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs | |||
@@ -51,10 +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 || CleaningUp || [Exit] } | 54 | /// Preparing => { Transferring || Cancelling || CleaningUp || Aborting || [Exit] } |
55 | /// Transferring => { ReceivedAtDestination || CleaningUp } | 55 | /// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp || Aborting } |
56 | /// ReceivedAtDestination => CleaningUp | 56 | /// Cancelling => CleaningUp || Aborting |
57 | /// ReceivedAtDestination => CleaningUp || Aborting | ||
57 | /// CleaningUp => [Exit] | 58 | /// CleaningUp => [Exit] |
59 | /// Aborting => [Exit] | ||
58 | /// | 60 | /// |
59 | /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp | 61 | /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp |
60 | /// 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. |
@@ -64,7 +66,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
64 | Preparing, // The agent is being prepared for transfer | 66 | Preparing, // The agent is being prepared for transfer |
65 | 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 |
66 | 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 |
67 | 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 |
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 | ||
68 | } | 72 | } |
69 | 73 | ||
70 | /// <summary> | 74 | /// <summary> |
@@ -115,42 +119,114 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
115 | /// <param name='newState'></param> | 119 | /// <param name='newState'></param> |
116 | /// <returns></returns> | 120 | /// <returns></returns> |
117 | /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> | 121 | /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> |
118 | internal void UpdateInTransit(UUID id, AgentTransferState newState) | 122 | internal bool UpdateInTransit(UUID id, AgentTransferState newState) |
119 | { | 123 | { |
124 | bool transitionOkay = false; | ||
125 | |||
126 | // We don't want to throw an exception on cancel since this can come it at any time. | ||
127 | bool failIfNotOkay = true; | ||
128 | |||
129 | // Should be a failure message if failure is not okay. | ||
130 | string failureMessage = null; | ||
131 | |||
132 | AgentTransferState? oldState = null; | ||
133 | |||
120 | lock (m_agentsInTransit) | 134 | lock (m_agentsInTransit) |
121 | { | 135 | { |
122 | // 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. |
123 | if (!m_agentsInTransit.ContainsKey(id)) | 137 | if (!m_agentsInTransit.ContainsKey(id)) |
124 | throw new Exception( | 138 | { |
125 | string.Format( | 139 | if (newState != AgentTransferState.Cancelling && newState != AgentTransferState.Aborting) |
126 | "Agent with ID {0} is not registered as in transit in {1}", | 140 | failureMessage = string.Format( |
127 | id, m_mod.Scene.RegionInfo.RegionName)); | 141 | "Agent with ID {0} is not registered as in transit in {1}", |
128 | 142 | id, m_mod.Scene.RegionInfo.RegionName); | |
129 | AgentTransferState oldState = m_agentsInTransit[id]; | 143 | else |
144 | failIfNotOkay = false; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | oldState = m_agentsInTransit[id]; | ||
130 | 149 | ||
131 | bool transitionOkay = false; | 150 | if (newState == AgentTransferState.Aborting) |
151 | { | ||
152 | transitionOkay = true; | ||
153 | } | ||
154 | else if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) | ||
155 | { | ||
156 | transitionOkay = true; | ||
157 | } | ||
158 | else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing) | ||
159 | { | ||
160 | transitionOkay = true; | ||
161 | } | ||
162 | else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring) | ||
163 | { | ||
164 | transitionOkay = true; | ||
165 | } | ||
166 | else | ||
167 | { | ||
168 | if (newState == AgentTransferState.Cancelling | ||
169 | && (oldState == AgentTransferState.Preparing || oldState == AgentTransferState.Transferring)) | ||
170 | { | ||
171 | transitionOkay = true; | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | failIfNotOkay = false; | ||
176 | } | ||
177 | } | ||
132 | 178 | ||
133 | if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) | 179 | if (!transitionOkay) |
134 | transitionOkay = true; | 180 | failureMessage |
135 | else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing) | 181 | = string.Format( |
136 | transitionOkay = true; | 182 | "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}", |
137 | else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring) | 183 | id, oldState, newState, m_mod.Scene.RegionInfo.RegionName); |
138 | transitionOkay = true; | 184 | } |
139 | 185 | ||
140 | if (transitionOkay) | 186 | if (transitionOkay) |
187 | { | ||
141 | m_agentsInTransit[id] = newState; | 188 | m_agentsInTransit[id] = newState; |
142 | else | 189 | |
143 | throw new Exception( | 190 | // m_log.DebugFormat( |
144 | string.Format( | 191 | // "[ENTITY TRANSFER STATE MACHINE]: Changed agent with id {0} from state {1} to {2} in {3}", |
145 | "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}", | 192 | // id, oldState, newState, m_mod.Scene.Name); |
146 | id, oldState, newState, m_mod.Scene.RegionInfo.RegionName)); | 193 | } |
194 | else if (failIfNotOkay) | ||
195 | { | ||
196 | throw new Exception(failureMessage); | ||
197 | } | ||
198 | // else | ||
199 | // { | ||
200 | // if (oldState != null) | ||
201 | // m_log.DebugFormat( | ||
202 | // "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} from state {1} to {2} in {3}", | ||
203 | // id, oldState, newState, m_mod.Scene.Name); | ||
204 | // else | ||
205 | // m_log.DebugFormat( | ||
206 | // "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} to state {1} in {2} since agent not in transit", | ||
207 | // id, newState, m_mod.Scene.Name); | ||
208 | // } | ||
147 | } | 209 | } |
210 | |||
211 | return transitionOkay; | ||
148 | } | 212 | } |
149 | 213 | ||
150 | internal bool IsInTransit(UUID id) | 214 | /// <summary> |
215 | /// Gets the current agent transfer state. | ||
216 | /// </summary> | ||
217 | /// <returns>Null if the agent is not in transit</returns> | ||
218 | /// <param name='id'> | ||
219 | /// Identifier. | ||
220 | /// </param> | ||
221 | internal AgentTransferState? GetAgentTransferState(UUID id) | ||
151 | { | 222 | { |
152 | lock (m_agentsInTransit) | 223 | lock (m_agentsInTransit) |
153 | return m_agentsInTransit.ContainsKey(id); | 224 | { |
225 | if (!m_agentsInTransit.ContainsKey(id)) | ||
226 | return null; | ||
227 | else | ||
228 | return m_agentsInTransit[id]; | ||
229 | } | ||
154 | } | 230 | } |
155 | 231 | ||
156 | /// <summary> | 232 | /// <summary> |
@@ -203,14 +279,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
203 | 279 | ||
204 | lock (m_agentsInTransit) | 280 | lock (m_agentsInTransit) |
205 | { | 281 | { |
206 | if (!IsInTransit(id)) | 282 | AgentTransferState? currentState = GetAgentTransferState(id); |
283 | |||
284 | if (currentState == null) | ||
207 | throw new Exception( | 285 | throw new Exception( |
208 | string.Format( | 286 | string.Format( |
209 | "Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit", | 287 | "Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit", |
210 | id, m_mod.Scene.RegionInfo.RegionName)); | 288 | id, m_mod.Scene.RegionInfo.RegionName)); |
211 | 289 | ||
212 | AgentTransferState currentState = m_agentsInTransit[id]; | ||
213 | |||
214 | if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination) | 290 | if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination) |
215 | throw new Exception( | 291 | throw new Exception( |
216 | string.Format( | 292 | string.Format( |
@@ -222,8 +298,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
222 | 298 | ||
223 | // There should be no race condition here since no other code should be removing the agent transfer or | 299 | // There should be no race condition here since no other code should be removing the agent transfer or |
224 | // changing the state to another other than Transferring => ReceivedAtDestination. | 300 | // changing the state to another other than Transferring => ReceivedAtDestination. |
225 | while (m_agentsInTransit[id] != AgentTransferState.ReceivedAtDestination && count-- > 0) | 301 | |
302 | while (count-- > 0) | ||
226 | { | 303 | { |
304 | lock (m_agentsInTransit) | ||
305 | { | ||
306 | if (m_agentsInTransit[id] == AgentTransferState.ReceivedAtDestination) | ||
307 | break; | ||
308 | } | ||
309 | |||
227 | // m_log.Debug(" >>> Waiting... " + count); | 310 | // m_log.Debug(" >>> Waiting... " + count); |
228 | Thread.Sleep(100); | 311 | Thread.Sleep(100); |
229 | } | 312 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index f3a0b01..d372c0e 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
199 | 199 | ||
200 | public override void RemoveRegion(Scene scene) | 200 | public override void RemoveRegion(Scene scene) |
201 | { | 201 | { |
202 | base.AddRegion(scene); | 202 | base.RemoveRegion(scene); |
203 | 203 | ||
204 | if (m_Enabled) | 204 | if (m_Enabled) |
205 | scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this); | 205 | scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this); |
@@ -212,11 +212,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
212 | protected override GridRegion GetFinalDestination(GridRegion region) | 212 | protected override GridRegion GetFinalDestination(GridRegion region) |
213 | { | 213 | { |
214 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); | 214 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); |
215 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); | 215 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionName, flags); |
216 | 216 | ||
217 | if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) | 217 | if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) |
218 | { | 218 | { |
219 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); | 219 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region is hyperlink"); |
220 | GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); | 220 | GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); |
221 | if (real_destination != null) | 221 | if (real_destination != null) |
222 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: GetFinalDestination serveruri -> {0}", real_destination.ServerURI); | 222 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: GetFinalDestination serveruri -> {0}", real_destination.ServerURI); |
diff --git a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs index 4004135..b9786ae 100644 --- a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs +++ b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs | |||
@@ -28,6 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using OpenSim.Region.Framework.Interfaces; | 30 | using OpenSim.Region.Framework.Interfaces; |
31 | using OpenMetaverse; | ||
31 | 32 | ||
32 | namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander | 33 | namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander |
33 | { | 34 | { |
@@ -152,6 +153,9 @@ namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander | |||
152 | case "Boolean": | 153 | case "Boolean": |
153 | m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); | 154 | m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); |
154 | break; | 155 | break; |
156 | case "UUID": | ||
157 | m_args[i].ArgumentValue = UUID.Parse(arg.ToString()); | ||
158 | break; | ||
155 | default: | 159 | default: |
156 | Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); | 160 | Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); |
157 | break; | 161 | break; |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index f8ec6de..7871eda 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | |||
@@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
71 | 71 | ||
72 | #region Internal functions | 72 | #region Internal functions |
73 | 73 | ||
74 | public AssetMetadata FetchMetadata(string url, UUID assetID) | 74 | private AssetMetadata FetchMetadata(string url, UUID assetID) |
75 | { | 75 | { |
76 | if (!url.EndsWith("/") && !url.EndsWith("=")) | 76 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
77 | url = url + "/"; | 77 | url = url + "/"; |
@@ -86,6 +86,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
86 | return meta; | 86 | return meta; |
87 | } | 87 | } |
88 | 88 | ||
89 | private AssetBase FetchAsset(string url, UUID assetID) | ||
90 | { | ||
91 | // Test if it's already here | ||
92 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); | ||
93 | if (asset == null) | ||
94 | { | ||
95 | if (!url.EndsWith("/") && !url.EndsWith("=")) | ||
96 | url = url + "/"; | ||
97 | |||
98 | asset = m_scene.AssetService.Get(url + assetID.ToString()); | ||
99 | |||
100 | //if (asset != null) | ||
101 | // m_log.DebugFormat("[HG ASSET MAPPER]: Fetched asset {0} of type {1} from {2} ", assetID, asset.Metadata.Type, url); | ||
102 | //else | ||
103 | // m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetch asset {0} from {1} ", assetID, url); | ||
104 | |||
105 | } | ||
106 | |||
107 | return asset; | ||
108 | } | ||
109 | |||
89 | public bool PostAsset(string url, AssetBase asset) | 110 | public bool PostAsset(string url, AssetBase asset) |
90 | { | 111 | { |
91 | if (asset != null) | 112 | if (asset != null) |
@@ -228,11 +249,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
228 | if (meta == null) | 249 | if (meta == null) |
229 | return; | 250 | return; |
230 | 251 | ||
231 | // The act of gathering UUIDs downloads the assets from the remote server | 252 | // The act of gathering UUIDs downloads some assets from the remote server |
253 | // but not all... | ||
232 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | 254 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); |
233 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); | 255 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); |
234 | uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); | 256 | uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); |
235 | 257 | m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); | |
258 | bool success = true; | ||
259 | foreach (UUID uuid in ids.Keys) | ||
260 | if (FetchAsset(userAssetURL, uuid) == null) | ||
261 | success = false; | ||
262 | |||
263 | // maybe all pieces got here... | ||
264 | if (!success) | ||
265 | m_log.DebugFormat("[HG ASSET MAPPER]: Problems getting item {0} from asset server {1}", assetID, userAssetURL); | ||
266 | else | ||
267 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL); | ||
236 | } | 268 | } |
237 | 269 | ||
238 | 270 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 964efda..b2b628d 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs | |||
@@ -88,12 +88,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
88 | IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; | 88 | IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; |
89 | if (thisModuleConfig != null) | 89 | if (thisModuleConfig != null) |
90 | { | 90 | { |
91 | // legacy configuration [obsolete] | 91 | m_HomeURI = Util.GetConfigVarFromSections<string>(source, "HomeURI", |
92 | m_HomeURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty); | 92 | new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty); |
93 | // preferred | 93 | m_ThisGatekeeper = Util.GetConfigVarFromSections<string>(source, "GatekeeperURI", |
94 | m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); | 94 | new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty); |
95 | // Legacy. Renove soon! | ||
96 | m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", m_ThisGatekeeper); | ||
97 | |||
95 | m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); | 98 | m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); |
96 | m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); | ||
97 | m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); | 99 | m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); |
98 | } | 100 | } |
99 | else | 101 | else |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 6e5a4a5..5aad7f0 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | |||
@@ -47,6 +47,7 @@ using OpenMetaverse; | |||
47 | using log4net; | 47 | using log4net; |
48 | using Nini.Config; | 48 | using Nini.Config; |
49 | using Mono.Addins; | 49 | using Mono.Addins; |
50 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
50 | 51 | ||
51 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | 52 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess |
52 | { | 53 | { |
@@ -398,7 +399,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
398 | objectGroup.RootPart.NextOwnerMask &= | 399 | objectGroup.RootPart.NextOwnerMask &= |
399 | ((uint)PermissionMask.Copy | | 400 | ((uint)PermissionMask.Copy | |
400 | (uint)PermissionMask.Transfer | | 401 | (uint)PermissionMask.Transfer | |
401 | (uint)PermissionMask.Modify); | 402 | (uint)PermissionMask.Modify | |
403 | (uint)PermissionMask.Export); | ||
402 | objectGroup.RootPart.NextOwnerMask |= | 404 | objectGroup.RootPart.NextOwnerMask |= |
403 | (uint)PermissionMask.Move; | 405 | (uint)PermissionMask.Move; |
404 | 406 | ||
@@ -506,7 +508,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
506 | InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions, | 508 | InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions, |
507 | IClientAPI remoteClient) | 509 | IClientAPI remoteClient) |
508 | { | 510 | { |
509 | uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7; | 511 | uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; |
510 | // For the porposes of inventory, an object is modify if the prims | 512 | // For the porposes of inventory, an object is modify if the prims |
511 | // are modify. This allows renaming an object that contains no | 513 | // are modify. This allows renaming an object that contains no |
512 | // mod items. | 514 | // mod items. |
@@ -555,6 +557,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
555 | (uint)PermissionMask.Transfer | | 557 | (uint)PermissionMask.Transfer | |
556 | (uint)PermissionMask.Modify | | 558 | (uint)PermissionMask.Modify | |
557 | (uint)PermissionMask.Move | | 559 | (uint)PermissionMask.Move | |
560 | (uint)PermissionMask.Export | | ||
558 | 7); // Preserve folded permissions | 561 | 7); // Preserve folded permissions |
559 | } | 562 | } |
560 | 563 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 21d8bd7..ad1a0e1 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs | |||
@@ -49,7 +49,7 @@ using OpenSim.Tests.Common.Mock; | |||
49 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests | 49 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests |
50 | { | 50 | { |
51 | [TestFixture] | 51 | [TestFixture] |
52 | public class InventoryAccessModuleTests | 52 | public class InventoryAccessModuleTests : OpenSimTestCase |
53 | { | 53 | { |
54 | protected TestScene m_scene; | 54 | protected TestScene m_scene; |
55 | protected BasicInventoryAccessModule m_iam; | 55 | protected BasicInventoryAccessModule m_iam; |
@@ -57,8 +57,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests | |||
57 | protected TestClient m_tc; | 57 | protected TestClient m_tc; |
58 | 58 | ||
59 | [SetUp] | 59 | [SetUp] |
60 | public void SetUp() | 60 | public override void SetUp() |
61 | { | 61 | { |
62 | base.SetUp(); | ||
63 | |||
62 | m_iam = new BasicInventoryAccessModule(); | 64 | m_iam = new BasicInventoryAccessModule(); |
63 | 65 | ||
64 | IConfigSource config = new IniConfigSource(); | 66 | IConfigSource config = new IniConfigSource(); |
@@ -107,7 +109,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests | |||
107 | item1.AssetID = asset1.FullID; | 109 | item1.AssetID = asset1.FullID; |
108 | item1.ID = item1Id; | 110 | item1.ID = item1Id; |
109 | InventoryFolderBase objsFolder | 111 | InventoryFolderBase objsFolder |
110 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, m_userId, "Objects")[0]; | 112 | = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; |
111 | item1.Folder = objsFolder.ID; | 113 | item1.Folder = objsFolder.ID; |
112 | m_scene.AddInventoryItem(item1); | 114 | m_scene.AddInventoryItem(item1); |
113 | 115 | ||
@@ -157,7 +159,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests | |||
157 | item1.AssetID = asset1.FullID; | 159 | item1.AssetID = asset1.FullID; |
158 | item1.ID = item1Id; | 160 | item1.ID = item1Id; |
159 | InventoryFolderBase objsFolder | 161 | InventoryFolderBase objsFolder |
160 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, m_userId, "Objects")[0]; | 162 | = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; |
161 | item1.Folder = objsFolder.ID; | 163 | item1.Folder = objsFolder.ID; |
162 | m_scene.AddInventoryItem(item1); | 164 | m_scene.AddInventoryItem(item1); |
163 | 165 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs index ec22146..d07cff4 100644 --- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs | |||
@@ -43,6 +43,7 @@ using OpenMetaverse; | |||
43 | using log4net; | 43 | using log4net; |
44 | using Mono.Addins; | 44 | using Mono.Addins; |
45 | using Nini.Config; | 45 | using Nini.Config; |
46 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
46 | 47 | ||
47 | namespace OpenSim.Region.CoreModules.Framework.Library | 48 | namespace OpenSim.Region.CoreModules.Framework.Library |
48 | { | 49 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index d84460a..64feec1 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs | |||
@@ -33,6 +33,7 @@ using log4net; | |||
33 | using Nini.Config; | 33 | using Nini.Config; |
34 | using OpenMetaverse; | 34 | using OpenMetaverse; |
35 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
36 | using OpenSim.Framework.Monitoring; | ||
36 | using OpenSim.Framework.Servers; | 37 | using OpenSim.Framework.Servers; |
37 | using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts; | 38 | using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts; |
38 | using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors; | 39 | using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors; |
@@ -100,6 +101,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
100 | "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage); | 101 | "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage); |
101 | 102 | ||
102 | AddMonitors(); | 103 | AddMonitors(); |
104 | RegisterStatsManagerRegionStatistics(); | ||
103 | } | 105 | } |
104 | 106 | ||
105 | public void RemoveRegion(Scene scene) | 107 | public void RemoveRegion(Scene scene) |
@@ -109,6 +111,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
109 | 111 | ||
110 | MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + m_scene.RegionInfo.RegionID); | 112 | MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + m_scene.RegionInfo.RegionID); |
111 | MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName)); | 113 | MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName)); |
114 | |||
115 | UnRegisterStatsManagerRegionStatistics(); | ||
116 | |||
112 | m_scene = null; | 117 | m_scene = null; |
113 | } | 118 | } |
114 | 119 | ||
@@ -399,6 +404,45 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
399 | { | 404 | { |
400 | m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")"); | 405 | m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")"); |
401 | } | 406 | } |
407 | |||
408 | private List<Stat> registeredStats = new List<Stat>(); | ||
409 | private void MakeStat(string pName, string pUnitName, Action<Stat> act) | ||
410 | { | ||
411 | Stat tempStat = new Stat(pName, pName, pName, pUnitName, "scene", m_scene.RegionInfo.RegionName, StatType.Pull, act, StatVerbosity.Info); | ||
412 | StatsManager.RegisterStat(tempStat); | ||
413 | registeredStats.Add(tempStat); | ||
414 | } | ||
415 | private void RegisterStatsManagerRegionStatistics() | ||
416 | { | ||
417 | MakeStat("RootAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetRootAgentCount(); }); | ||
418 | MakeStat("ChildAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetChildAgentCount(); }); | ||
419 | MakeStat("TotalPrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetTotalObjectsCount(); }); | ||
420 | MakeStat("ActivePrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetActiveObjectsCount(); }); | ||
421 | MakeStat("ActiveScripts", "scripts", (s) => { s.Value = m_scene.SceneGraph.GetActiveScriptsCount(); }); | ||
422 | |||
423 | MakeStat("TimeDilation", "sec/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[0]; }); | ||
424 | MakeStat("SimFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[1]; }); | ||
425 | MakeStat("PhysicsFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[2]; }); | ||
426 | MakeStat("AgentUpdates", "updates/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[3]; }); | ||
427 | MakeStat("FrameTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[8]; }); | ||
428 | MakeStat("NetTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[9]; }); | ||
429 | MakeStat("OtherTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[12]; }); | ||
430 | MakeStat("PhysicsTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[10]; }); | ||
431 | MakeStat("AgentTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[16]; }); | ||
432 | MakeStat("ImageTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[11]; }); | ||
433 | MakeStat("ScriptLines", "lines/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[20]; }); | ||
434 | MakeStat("SimSpareMS", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[21]; }); | ||
435 | } | ||
436 | |||
437 | private void UnRegisterStatsManagerRegionStatistics() | ||
438 | { | ||
439 | foreach (Stat stat in registeredStats) | ||
440 | { | ||
441 | StatsManager.DeregisterStat(stat); | ||
442 | stat.Dispose(); | ||
443 | } | ||
444 | registeredStats.Clear(); | ||
445 | } | ||
402 | 446 | ||
403 | } | 447 | } |
404 | } | 448 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs index fb74cc6..f3436d1 100644 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs | |||
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
57 | try | 57 | try |
58 | { | 58 | { |
59 | IConfig statConfig = source.Configs["Statistics.Binary"]; | 59 | IConfig statConfig = source.Configs["Statistics.Binary"]; |
60 | if (statConfig.Contains("enabled") && statConfig.GetBoolean("enabled")) | 60 | if (statConfig != null && statConfig.Contains("enabled") && statConfig.GetBoolean("enabled")) |
61 | { | 61 | { |
62 | if (statConfig.Contains("collect_region_stats")) | 62 | if (statConfig.Contains("collect_region_stats")) |
63 | { | 63 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs index fd8d5e3..2fe9026 100755 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs | |||
@@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
52 | private TimeSpan m_logFileLife; | 52 | private TimeSpan m_logFileLife; |
53 | private DateTime m_logFileEndTime; | 53 | private DateTime m_logFileEndTime; |
54 | private Object m_logFileWriteLock = new Object(); | 54 | private Object m_logFileWriteLock = new Object(); |
55 | private bool m_flushWrite; | ||
55 | 56 | ||
56 | // set externally when debugging. If let 'null', this does not write any error messages. | 57 | // set externally when debugging. If let 'null', this does not write any error messages. |
57 | public ILog ErrorLogger = null; | 58 | public ILog ErrorLogger = null; |
@@ -73,7 +74,9 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
73 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> | 74 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> |
74 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> | 75 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> |
75 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> | 76 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> |
76 | public LogWriter(string dir, string headr, int maxFileTime) | 77 | /// <param name="flushWrite">Whether to do a flush after every log write. Best left off but |
78 | /// if one is looking for a crash, this is a good thing to turn on.</param> | ||
79 | public LogWriter(string dir, string headr, int maxFileTime, bool flushWrite) | ||
77 | { | 80 | { |
78 | m_logDirectory = dir == null ? "." : dir; | 81 | m_logDirectory = dir == null ? "." : dir; |
79 | 82 | ||
@@ -86,8 +89,14 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
86 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); | 89 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); |
87 | m_logFileEndTime = DateTime.Now + m_logFileLife; | 90 | m_logFileEndTime = DateTime.Now + m_logFileLife; |
88 | 91 | ||
92 | m_flushWrite = flushWrite; | ||
93 | |||
89 | Enabled = true; | 94 | Enabled = true; |
90 | } | 95 | } |
96 | // Constructor that assumes flushWrite is off. | ||
97 | public LogWriter(string dir, string headr, int maxFileTime) : this(dir, headr, maxFileTime, false) | ||
98 | { | ||
99 | } | ||
91 | 100 | ||
92 | public void Dispose() | 101 | public void Dispose() |
93 | { | 102 | { |
@@ -127,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
127 | { | 136 | { |
128 | lock (m_logFileWriteLock) | 137 | lock (m_logFileWriteLock) |
129 | { | 138 | { |
130 | DateTime now = DateTime.Now; | 139 | DateTime now = DateTime.UtcNow; |
131 | if (m_logFile == null || now > m_logFileEndTime) | 140 | if (m_logFile == null || now > m_logFileEndTime) |
132 | { | 141 | { |
133 | if (m_logFile != null) | 142 | if (m_logFile != null) |
@@ -153,6 +162,8 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
153 | buff.Append(line); | 162 | buff.Append(line); |
154 | buff.Append("\r\n"); | 163 | buff.Append("\r\n"); |
155 | m_logFile.Write(buff.ToString()); | 164 | m_logFile.Write(buff.ToString()); |
165 | if (m_flushWrite) | ||
166 | m_logFile.Flush(); | ||
156 | } | 167 | } |
157 | } | 168 | } |
158 | } | 169 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 86e7004..77e8b00 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | |||
@@ -181,6 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
181 | 181 | ||
182 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); | 182 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); |
183 | 183 | ||
184 | // searhc the user accounts service | ||
184 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); | 185 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); |
185 | 186 | ||
186 | List<UserData> users = new List<UserData>(); | 187 | List<UserData> users = new List<UserData>(); |
@@ -196,6 +197,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
196 | } | 197 | } |
197 | } | 198 | } |
198 | 199 | ||
200 | // search the local cache | ||
201 | foreach (UserData data in m_UserCache.Values) | ||
202 | if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && | ||
203 | (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query))) | ||
204 | users.Add(data); | ||
205 | |||
199 | AddAdditionalUsers(avatarID, query, users); | 206 | AddAdditionalUsers(avatarID, query, users); |
200 | 207 | ||
201 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); | 208 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); |
@@ -433,6 +440,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
433 | public void AddUser(UUID uuid, string first, string last, string homeURL) | 440 | public void AddUser(UUID uuid, string first, string last, string homeURL) |
434 | { | 441 | { |
435 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); | 442 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); |
443 | if (homeURL == string.Empty) | ||
444 | return; | ||
445 | |||
436 | AddUser(uuid, homeURL + ";" + first + " " + last); | 446 | AddUser(uuid, homeURL + ";" + first + " " + last); |
437 | } | 447 | } |
438 | 448 | ||