clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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.Net;
31 using System.Reflection;
32 using System.Threading;
33 using OpenMetaverse;
34 using OpenMetaverse.StructuredData;
35 using log4net;
36 using OpenSim.Framework;
37 using OpenSim.Framework.Client;
38 using OpenSim.Framework.Communications;
39 using OpenSim.Framework.Capabilities;
40 using OpenSim.Region.Framework.Interfaces;
41 using OpenSim.Services.Interfaces;
42 using OSD = OpenMetaverse.StructuredData.OSD;
43 using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44  
45 namespace OpenSim.Region.Framework.Scenes
46 {
47 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
48  
49 /// <summary>
50 /// Class that Region communications runs through
51 /// </summary>
52 public class SceneCommunicationService //one instance per region
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static string LogHeader = "[SCENE COMMUNIATION SERVICE]";
56  
57 protected RegionInfo m_regionInfo;
58 protected Scene m_scene;
59  
60 public void SetScene(Scene s)
61 {
62 m_scene = s;
63 m_regionInfo = s.RegionInfo;
64 }
65  
66 public delegate void InformNeighbourThatRegionUpDelegate(INeighbourService nService, RegionInfo region, ulong regionhandle);
67  
68 private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
69 {
70 InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState;
71 icon.EndInvoke(iar);
72 }
73  
74 /// <summary>
75 /// Asynchronous call to information neighbouring regions that this region is up
76 /// </summary>
77 /// <param name="region"></param>
78 /// <param name="regionhandle"></param>
79 private void InformNeighboursThatRegionIsUpAsync(INeighbourService neighbourService, RegionInfo region, ulong regionhandle)
80 {
81 uint x = 0, y = 0;
82 Utils.LongToUInts(regionhandle, out x, out y);
83  
84 GridRegion neighbour = null;
85 if (neighbourService != null)
86 neighbour = neighbourService.HelloNeighbour(regionhandle, region);
87 else
88 m_log.DebugFormat( "{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name);
89  
90 if (neighbour != null)
91 {
92 m_log.DebugFormat( "{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up",
93 LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
94  
95 m_scene.EventManager.TriggerOnRegionUp(neighbour);
96 }
97 else
98 {
99 m_log.WarnFormat(
100 "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.",
101 m_scene.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
102 }
103 }
104  
105 public void InformNeighborsThatRegionisUp(INeighbourService neighbourService, RegionInfo region)
106 {
107 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
108  
109 List<GridRegion> neighbours
110 = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
111  
112 m_log.DebugFormat("{0} Informing {1} neighbours that region {2} is up", LogHeader, neighbours.Count, m_scene.Name);
113  
114 foreach (GridRegion n in neighbours)
115 {
116 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
117 d.BeginInvoke(neighbourService, region, n.RegionHandle,
118 InformNeighborsThatRegionisUpCompleted,
119 d);
120 }
121 }
122  
123 public delegate void SendChildAgentDataUpdateDelegate(AgentPosition cAgentData, UUID scopeID, GridRegion dest);
124  
125 /// <summary>
126 /// This informs all neighboring regions about the settings of it's child agent.
127 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
128 ///
129 /// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
130 ///
131 /// </summary>
132 private void SendChildAgentDataUpdateAsync(AgentPosition cAgentData, UUID scopeID, GridRegion dest)
133 {
134 //m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName);
135 try
136 {
137 m_scene.SimulationService.UpdateAgent(dest, cAgentData);
138 }
139 catch
140 {
141 // Ignore; we did our best
142 }
143 }
144  
145 private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
146 {
147 SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState;
148 icon.EndInvoke(iar);
149 }
150  
151 public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence)
152 {
153 // m_log.DebugFormat(
154 // "[SCENE COMMUNICATION SERVICE]: Sending child agent position updates for {0} in {1}",
155 // presence.Name, m_scene.Name);
156  
157 // This assumes that we know what our neighbors are.
158 try
159 {
160 uint x = 0, y = 0;
161 List<string> simulatorList = new List<string>();
162 foreach (ulong regionHandle in presence.KnownRegionHandles)
163 {
164 if (regionHandle != m_regionInfo.RegionHandle)
165 {
166 // we only want to send one update to each simulator; the simulator will
167 // hand it off to the regions where a child agent exists, this does assume
168 // that the region position is cached or performance will degrade
169 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
170 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
171 if (dest == null)
172 continue;
173  
174 if (!simulatorList.Contains(dest.ServerURI))
175 {
176 // we havent seen this simulator before, add it to the list
177 // and send it an update
178 simulatorList.Add(dest.ServerURI);
179 // Let move this to sync. Mono definitely does not like async networking.
180 m_scene.SimulationService.UpdateAgent(dest, cAgentData);
181  
182 // Leaving this here as a reminder that we tried, and it sucks.
183 //SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
184 //d.BeginInvoke(cAgentData, m_regionInfo.ScopeID, dest,
185 // SendChildAgentDataUpdateCompleted,
186 // d);
187 }
188 }
189 }
190 }
191 catch (InvalidOperationException)
192 {
193 // We're ignoring a collection was modified error because this data gets old and outdated fast.
194 }
195 }
196  
197 /// <summary>
198 /// Closes a child agent on a given region
199 /// </summary>
200 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
201 {
202 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
203  
204 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
205 uint x = 0, y = 0;
206 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
207  
208 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
209  
210 m_log.DebugFormat(
211 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
212  
213 m_scene.SimulationService.CloseAgent(destination, agentID, auth_token);
214 }
215  
216 /// <summary>
217 /// Closes a child agents in a collection of regions. Does so asynchronously
218 /// so that the caller doesn't wait.
219 /// </summary>
220 /// <param name="agentID"></param>
221 /// <param name="regionslst"></param>
222 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
223 {
224 foreach (ulong handle in regionslst)
225 {
226 // We must take a copy here since handle is acts like a reference when used in an iterator.
227 // This leads to race conditions if directly passed to SendCloseChildAgent with more than one neighbour region.
228 ulong handleCopy = handle;
229 Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); });
230 }
231 }
232  
233 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
234 {
235 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
236 }
237 }
238 }