aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/WorldMap
diff options
context:
space:
mode:
authorMelanie2012-07-08 10:44:53 +0200
committerMelanie2012-07-08 10:44:53 +0200
commit1e4c65649736db82d0221b6b2aa57f7f45c7163c (patch)
tree064b128509b7a91ebebbf94d094c1a25be16a9da /OpenSim/Region/CoreModules/World/WorldMap
parentInstead of sending 20 records in 2 packets, send just one as we intended in t... (diff)
downloadopensim-SC_OLD-1e4c65649736db82d0221b6b2aa57f7f45c7163c.zip
opensim-SC_OLD-1e4c65649736db82d0221b6b2aa57f7f45c7163c.tar.gz
opensim-SC_OLD-1e4c65649736db82d0221b6b2aa57f7f45c7163c.tar.bz2
opensim-SC_OLD-1e4c65649736db82d0221b6b2aa57f7f45c7163c.tar.xz
Revamp map block sending to eliminate overload of the grid server connection
and the sim's http client
Diffstat (limited to 'OpenSim/Region/CoreModules/World/WorldMap')
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs298
1 files changed, 202 insertions, 96 deletions
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 88aacb9..a226b78 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -66,6 +66,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
66 private ManualResetEvent queueEvent = new ManualResetEvent(false); 66 private ManualResetEvent queueEvent = new ManualResetEvent(false);
67 private Queue<MapRequestState> requests = new Queue<MapRequestState>(); 67 private Queue<MapRequestState> requests = new Queue<MapRequestState>();
68 68
69 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
70 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
71
69 protected Scene m_scene; 72 protected Scene m_scene;
70 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 73 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
71 private int cachedTime = 0; 74 private int cachedTime = 0;
@@ -227,54 +230,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
227 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is 230 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
228 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. 231 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
229 232
230 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) 233 //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
231 { 234 //{
232 ScenePresence avatarPresence = null; 235 // ScenePresence avatarPresence = null;
233 236
234 m_scene.TryGetScenePresence(agentID, out avatarPresence); 237 // m_scene.TryGetScenePresence(agentID, out avatarPresence);
235 238
236 if (avatarPresence != null) 239 // if (avatarPresence != null)
237 { 240 // {
238 bool lookup = false; 241 // bool lookup = false;
239 242
240 lock (cachedMapBlocks) 243 // lock (cachedMapBlocks)
241 { 244 // {
242 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) 245 // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
243 { 246 // {
244 List<MapBlockData> mapBlocks; 247 // List<MapBlockData> mapBlocks;
245 248
246 mapBlocks = cachedMapBlocks; 249 // mapBlocks = cachedMapBlocks;
247 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 250 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
248 } 251 // }
249 else 252 // else
250 { 253 // {
251 lookup = true; 254 // lookup = true;
252 } 255 // }
253 } 256 // }
254 if (lookup) 257 // if (lookup)
255 { 258 // {
256 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 259 // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
257 260
258 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 261 // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
259 (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, 262 // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
260 (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, 263 // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
261 (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, 264 // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
262 (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); 265 // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
263 foreach (GridRegion r in regions) 266 // foreach (GridRegion r in regions)
264 { 267 // {
265 MapBlockData block = new MapBlockData(); 268 // MapBlockData block = new MapBlockData();
266 MapBlockFromGridRegion(block, r, 0); 269 // MapBlockFromGridRegion(block, r, 0);
267 mapBlocks.Add(block); 270 // mapBlocks.Add(block);
268 } 271 // }
269 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 272 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
270 273
271 lock (cachedMapBlocks) 274 // lock (cachedMapBlocks)
272 cachedMapBlocks = mapBlocks; 275 // cachedMapBlocks = mapBlocks;
273 276
274 cachedTime = Util.UnixTimeSinceEpoch(); 277 // cachedTime = Util.UnixTimeSinceEpoch();
275 } 278 // }
276 } 279 // }
277 } 280 //}
278 281
279 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 282 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
280 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 283 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@@ -301,8 +304,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
301 protected static OSDMapLayer GetOSDMapLayerResponse() 304 protected static OSDMapLayer GetOSDMapLayerResponse()
302 { 305 {
303 OSDMapLayer mapLayer = new OSDMapLayer(); 306 OSDMapLayer mapLayer = new OSDMapLayer();
304 mapLayer.Right = 5000; 307 mapLayer.Right = 2048;
305 mapLayer.Top = 5000; 308 mapLayer.Top = 2048;
306 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); 309 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
307 310
308 return mapLayer; 311 return mapLayer;
@@ -331,6 +334,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
331 { 334 {
332 m_rootAgents.Remove(AgentId); 335 m_rootAgents.Remove(AgentId);
333 } 336 }
337 lock (m_mapBlockRequestEvent)
338 {
339 if (m_mapBlockRequests.ContainsKey(AgentId))
340 m_mapBlockRequests.Remove(AgentId);
341 }
334 } 342 }
335 #endregion 343 #endregion
336 344
@@ -353,6 +361,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
353 ThreadPriority.BelowNormal, 361 ThreadPriority.BelowNormal,
354 true, 362 true,
355 true); 363 true);
364 Watchdog.StartThread(
365 MapBlockSendThread,
366 string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
367 ThreadPriority.BelowNormal,
368 true,
369 true);
356 } 370 }
357 371
358 /// <summary> 372 /// <summary>
@@ -373,6 +387,22 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
373 queueEvent.Set(); 387 queueEvent.Set();
374 requests.Enqueue(st); 388 requests.Enqueue(st);
375 } 389 }
390
391 MapBlockRequestData req = new MapBlockRequestData();
392
393 req.client = null;
394 req.minX = 0;
395 req.maxX = 0;
396 req.minY = 0;
397 req.maxY = 0;
398 req.flags = 0;
399
400 lock (m_mapBlockRequestEvent)
401 {
402 m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
403 m_mapBlockRequests[UUID.Zero].Enqueue(req);
404 m_mapBlockRequestEvent.Set();
405 }
376 } 406 }
377 407
378 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 408 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -932,84 +962,144 @@ return;
932 /// <param name="minY"></param> 962 /// <param name="minY"></param>
933 /// <param name="maxX"></param> 963 /// <param name="maxX"></param>
934 /// <param name="maxY"></param> 964 /// <param name="maxY"></param>
935 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 965 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
936 { 966 {
937 Util.FireAndForget(x => 967 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
968 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible
938 { 969 {
939 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); 970 List<MapBlockData> response = new List<MapBlockData>();
940 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible 971
972 // this should return one mapblock at most. It is triggered by a click
973 // on an unloaded square.
974 // But make sure: Look whether the one we requested is in there
975 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
976 minX * (int)Constants.RegionSize,
977 maxX * (int)Constants.RegionSize,
978 minY * (int)Constants.RegionSize,
979 maxY * (int)Constants.RegionSize);
980
981 if (regions != null)
941 { 982 {
942 List<MapBlockData> response = new List<MapBlockData>(); 983 foreach (GridRegion r in regions)
943
944 // this should return one mapblock at most. It is triggered by a click
945 // on an unloaded square.
946 // But make sure: Look whether the one we requested is in there
947 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
948 minX * (int)Constants.RegionSize,
949 maxX * (int)Constants.RegionSize,
950 minY * (int)Constants.RegionSize,
951 maxY * (int)Constants.RegionSize);
952
953 if (regions != null)
954 { 984 {
955 foreach (GridRegion r in regions) 985 if ((r.RegionLocX == minX * (int)Constants.RegionSize) &&
986 (r.RegionLocY == minY * (int)Constants.RegionSize))
956 { 987 {
957 if ((r.RegionLocX == minX * (int)Constants.RegionSize) && 988 // found it => add it to response
958 (r.RegionLocY == minY * (int)Constants.RegionSize)) 989 MapBlockData block = new MapBlockData();
959 { 990 MapBlockFromGridRegion(block, r, flag);
960 // found it => add it to response 991 response.Add(block);
961 MapBlockData block = new MapBlockData(); 992 break;
962 MapBlockFromGridRegion(block, r, flag);
963 response.Add(block);
964 break;
965 }
966 } 993 }
967 } 994 }
995 }
968 996
969 if (response.Count == 0) 997 if (response.Count == 0)
998 {
999 // response still empty => couldn't find the map-tile the user clicked on => tell the client
1000 MapBlockData block = new MapBlockData();
1001 block.X = (ushort)minX;
1002 block.Y = (ushort)minY;
1003 block.Access = 254; // means 'simulator is offline'
1004 response.Add(block);
1005 }
1006 // The lower 16 bits are an unsigned int16
1007 remoteClient.SendMapBlock(response, flag & 0xffff);
1008 }
1009 else
1010 {
1011 // normal mapblock request. Use the provided values
1012 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
1013 }
1014 }
1015
1016 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1017 {
1018 MapBlockRequestData req = new MapBlockRequestData();
1019
1020 req.client = remoteClient;
1021 req.minX = minX;
1022 req.maxX = maxX;
1023 req.minY = minY;
1024 req.maxY = maxY;
1025 req.flags = flag;
1026
1027 lock (m_mapBlockRequestEvent)
1028 {
1029 if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId))
1030 m_mapBlockRequests[remoteClient.AgentId] = new Queue<MapBlockRequestData>();
1031 m_mapBlockRequests[remoteClient.AgentId].Enqueue(req);
1032 m_mapBlockRequestEvent.Set();
1033 }
1034
1035 return new List<MapBlockData>();
1036 }
1037
1038 protected void MapBlockSendThread()
1039 {
1040 while (true)
1041 {
1042 List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
1043
1044 m_mapBlockRequestEvent.WaitOne();
1045 lock (m_mapBlockRequestEvent)
1046 {
1047 int total = 0;
1048 foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
970 { 1049 {
971 // response still empty => couldn't find the map-tile the user clicked on => tell the client 1050 if (q.Count > 0)
972 MapBlockData block = new MapBlockData(); 1051 thisRunData.Add(q.Dequeue());
973 block.X = (ushort)minX; 1052
974 block.Y = (ushort)minY; 1053 total += q.Count;
975 block.Access = 254; // means 'simulator is offline'
976 response.Add(block);
977 } 1054 }
978 // The lower 16 bits are an unsigned int16 1055
979 remoteClient.SendMapBlock(response, flag & 0xffff); 1056 if (total == 0)
1057 m_mapBlockRequestEvent.Reset();
980 } 1058 }
981 else 1059
1060 foreach (MapBlockRequestData req in thisRunData)
982 { 1061 {
983 // normal mapblock request. Use the provided values 1062 // Null client stops thread
984 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); 1063 if (req.client == null)
1064 return;
1065
1066 GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
985 } 1067 }
986 }); 1068
1069 Thread.Sleep(50);
1070 }
987 } 1071 }
988 1072
989 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1073 protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
990 { 1074 {
1075 List<MapBlockData> allBlocks = new List<MapBlockData>();
991 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1076 List<MapBlockData> mapBlocks = new List<MapBlockData>();
992 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1077 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
993 (minX - 4) * (int)Constants.RegionSize, 1078 minX * (int)Constants.RegionSize,
994 (maxX + 4) * (int)Constants.RegionSize, 1079 maxX * (int)Constants.RegionSize,
995 (minY - 4) * (int)Constants.RegionSize, 1080 minY * (int)Constants.RegionSize,
996 (maxY + 4) * (int)Constants.RegionSize); 1081 maxY * (int)Constants.RegionSize);
1082// (minX - 4) * (int)Constants.RegionSize,
1083// (maxX + 4) * (int)Constants.RegionSize,
1084// (minY - 4) * (int)Constants.RegionSize,
1085// (maxY + 4) * (int)Constants.RegionSize);
997 foreach (GridRegion r in regions) 1086 foreach (GridRegion r in regions)
998 { 1087 {
999 MapBlockData block = new MapBlockData(); 1088 MapBlockData block = new MapBlockData();
1000 MapBlockFromGridRegion(block, r, flag); 1089 MapBlockFromGridRegion(block, r, flag);
1001 mapBlocks.Add(block); 1090 mapBlocks.Add(block);
1091 allBlocks.Add(block);
1002 if (mapBlocks.Count >= 10) 1092 if (mapBlocks.Count >= 10)
1003 { 1093 {
1004 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1094 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1005 mapBlocks.Clear(); 1095 mapBlocks.Clear();
1006 Thread.Sleep(1000); 1096 Thread.Sleep(50);
1007 } 1097 }
1008 } 1098 }
1009 if (mapBlocks.Count > 0) 1099 if (mapBlocks.Count > 0)
1010 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1100 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1011 1101
1012 return mapBlocks; 1102 return allBlocks;
1013 } 1103 }
1014 1104
1015 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag) 1105 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
@@ -1408,6 +1498,12 @@ return;
1408 { 1498 {
1409 m_rootAgents.Remove(avatar.UUID); 1499 m_rootAgents.Remove(avatar.UUID);
1410 } 1500 }
1501
1502 lock (m_mapBlockRequestEvent)
1503 {
1504 if (m_mapBlockRequests.ContainsKey(avatar.UUID))
1505 m_mapBlockRequests.Remove(avatar.UUID);
1506 }
1411 } 1507 }
1412 1508
1413 public void OnRegionUp(GridRegion otherRegion) 1509 public void OnRegionUp(GridRegion otherRegion)
@@ -1531,4 +1627,14 @@ return;
1531 public uint itemtype; 1627 public uint itemtype;
1532 public ulong regionhandle; 1628 public ulong regionhandle;
1533 } 1629 }
1630
1631 public struct MapBlockRequestData
1632 {
1633 public IClientAPI client;
1634 public int minX;
1635 public int minY;
1636 public int maxX;
1637 public int maxY;
1638 public uint flags;
1639 }
1534} 1640}