aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs624
1 files changed, 358 insertions, 266 deletions
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index cdf1467..98fa763 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -66,7 +66,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
66 private static readonly UUID STOP_UUID = UUID.Random(); 66 private static readonly UUID STOP_UUID = UUID.Random();
67 private static readonly string m_mapLayerPath = "0001/"; 67 private static readonly string m_mapLayerPath = "0001/";
68 68
69 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>(); 69 private ManualResetEvent queueEvent = new ManualResetEvent(false);
70 private Queue<MapRequestState> requests = new Queue<MapRequestState>();
71
72 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
73 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
70 74
71 protected Scene m_scene; 75 protected Scene m_scene;
72 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 76 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
@@ -74,15 +78,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
74 private int blacklistTimeout = 10*60*1000; // 10 minutes 78 private int blacklistTimeout = 10*60*1000; // 10 minutes
75 private byte[] myMapImageJPEG; 79 private byte[] myMapImageJPEG;
76 protected volatile bool m_Enabled = false; 80 protected volatile bool m_Enabled = false;
77 private Dictionary<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>();
78 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); 81 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>();
79 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 82 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>();
80 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 83 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>();
81 private List<UUID> m_rootAgents = new List<UUID>(); 84 private List<UUID> m_rootAgents = new List<UUID>();
82 private volatile bool threadrunning = false; 85 private volatile bool threadrunning = false;
83 86
84 private IServiceThrottleModule m_ServiceThrottle;
85
86 //private int CacheRegionsDistance = 256; 87 //private int CacheRegionsDistance = 256;
87 88
88 #region INonSharedRegionModule Members 89 #region INonSharedRegionModule Members
@@ -93,7 +94,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
93 if (Util.GetConfigVarFromSections<string>( 94 if (Util.GetConfigVarFromSections<string>(
94 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap") 95 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
95 m_Enabled = true; 96 m_Enabled = true;
96 97
97 blacklistTimeout 98 blacklistTimeout
98 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000; 99 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
99 } 100 }
@@ -133,10 +134,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
133 134
134 public virtual void RegionLoaded (Scene scene) 135 public virtual void RegionLoaded (Scene scene)
135 { 136 {
136 if (!m_Enabled)
137 return;
138
139 m_ServiceThrottle = scene.RequestModuleInterface<IServiceThrottleModule>();
140 } 137 }
141 138
142 139
@@ -185,13 +182,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
185 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; 182 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent;
186 m_scene.EventManager.OnRegionUp += OnRegionUp; 183 m_scene.EventManager.OnRegionUp += OnRegionUp;
187 184
188// StartThread(new object()); 185 StartThread(new object());
189 } 186 }
190 187
191 // this has to be called with a lock on m_scene 188 // this has to be called with a lock on m_scene
192 protected virtual void RemoveHandlers() 189 protected virtual void RemoveHandlers()
193 { 190 {
194// StopThread(); 191 StopThread();
195 192
196 m_scene.EventManager.OnRegionUp -= OnRegionUp; 193 m_scene.EventManager.OnRegionUp -= OnRegionUp;
197 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent; 194 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent;
@@ -249,54 +246,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
249 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is 246 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
250 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. 247 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
251 248
252 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) 249 //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
253 { 250 //{
254 ScenePresence avatarPresence = null; 251 // ScenePresence avatarPresence = null;
255 252
256 m_scene.TryGetScenePresence(agentID, out avatarPresence); 253 // m_scene.TryGetScenePresence(agentID, out avatarPresence);
257 254
258 if (avatarPresence != null) 255 // if (avatarPresence != null)
259 { 256 // {
260 bool lookup = false; 257 // bool lookup = false;
261 258
262 lock (cachedMapBlocks) 259 // lock (cachedMapBlocks)
263 { 260 // {
264 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) 261 // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
265 { 262 // {
266 List<MapBlockData> mapBlocks; 263 // List<MapBlockData> mapBlocks;
267 264
268 mapBlocks = cachedMapBlocks; 265 // mapBlocks = cachedMapBlocks;
269 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 266 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
270 } 267 // }
271 else 268 // else
272 { 269 // {
273 lookup = true; 270 // lookup = true;
274 } 271 // }
275 } 272 // }
276 if (lookup) 273 // if (lookup)
277 { 274 // {
278 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 275 // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
279 276
280 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 277 // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
281 (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, 278 // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
282 (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, 279 // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
283 (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, 280 // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
284 (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); 281 // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
285 foreach (GridRegion r in regions) 282 // foreach (GridRegion r in regions)
286 { 283 // {
287 MapBlockData block = new MapBlockData(); 284 // MapBlockData block = new MapBlockData();
288 MapBlockFromGridRegion(block, r, 0); 285 // MapBlockFromGridRegion(block, r, 0);
289 mapBlocks.Add(block); 286 // mapBlocks.Add(block);
290 } 287 // }
291 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 288 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
292 289
293 lock (cachedMapBlocks) 290 // lock (cachedMapBlocks)
294 cachedMapBlocks = mapBlocks; 291 // cachedMapBlocks = mapBlocks;
295 292
296 cachedTime = Util.UnixTimeSinceEpoch(); 293 // cachedTime = Util.UnixTimeSinceEpoch();
297 } 294 // }
298 } 295 // }
299 } 296 //}
300 297
301 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 298 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
302 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 299 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@@ -323,8 +320,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
323 protected static OSDMapLayer GetOSDMapLayerResponse() 320 protected static OSDMapLayer GetOSDMapLayerResponse()
324 { 321 {
325 OSDMapLayer mapLayer = new OSDMapLayer(); 322 OSDMapLayer mapLayer = new OSDMapLayer();
326 mapLayer.Right = 5000; 323 mapLayer.Right = 2048;
327 mapLayer.Top = 5000; 324 mapLayer.Top = 2048;
328 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); 325 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
329 326
330 return mapLayer; 327 return mapLayer;
@@ -353,6 +350,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
353 { 350 {
354 m_rootAgents.Remove(AgentId); 351 m_rootAgents.Remove(AgentId);
355 } 352 }
353 lock (m_mapBlockRequestEvent)
354 {
355 if (m_mapBlockRequests.ContainsKey(AgentId))
356 m_mapBlockRequests.Remove(AgentId);
357 }
356 } 358 }
357 #endregion 359 #endregion
358 360
@@ -375,6 +377,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
375 ThreadPriority.BelowNormal, 377 ThreadPriority.BelowNormal,
376 true, 378 true,
377 true); 379 true);
380 Watchdog.StartThread(
381 MapBlockSendThread,
382 string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
383 ThreadPriority.BelowNormal,
384 true,
385 true);
378 } 386 }
379 387
380 /// <summary> 388 /// <summary>
@@ -390,7 +398,27 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
390 st.itemtype=0; 398 st.itemtype=0;
391 st.regionhandle=0; 399 st.regionhandle=0;
392 400
393 requests.Enqueue(st); 401 lock (requests)
402 {
403 queueEvent.Set();
404 requests.Enqueue(st);
405 }
406
407 MapBlockRequestData req = new MapBlockRequestData();
408
409 req.client = null;
410 req.minX = 0;
411 req.maxX = 0;
412 req.minY = 0;
413 req.maxY = 0;
414 req.flags = 0;
415
416 lock (m_mapBlockRequestEvent)
417 {
418 m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
419 m_mapBlockRequests[UUID.Zero].Enqueue(req);
420 m_mapBlockRequestEvent.Set();
421 }
394 } 422 }
395 423
396 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 424 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -541,12 +569,26 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
541 /// </summary> 569 /// </summary>
542 public void process() 570 public void process()
543 { 571 {
544 //const int MAX_ASYNC_REQUESTS = 20; 572 const int MAX_ASYNC_REQUESTS = 20;
545 try 573 try
546 { 574 {
547 while (true) 575 while (true)
548 { 576 {
549 MapRequestState st = requests.Dequeue(1000); 577 MapRequestState st = new MapRequestState();
578 bool valid = false;
579 queueEvent.WaitOne();
580 lock (requests)
581 {
582 if (requests.Count > 0)
583 {
584 st = requests.Dequeue();
585 valid = true;
586 }
587 if (requests.Count == 0)
588 queueEvent.Reset();
589 }
590 if (!valid)
591 continue;
550 592
551 // end gracefully 593 // end gracefully
552 if (st.agentID == STOP_UUID) 594 if (st.agentID == STOP_UUID)
@@ -564,13 +606,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
564 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 606 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
565 { 607 {
566 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 608 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
567 Thread.Sleep(80); 609 Thread.Sleep(100);
568 610
569 RequestMapItemsDelegate d = RequestMapItemsAsync;
570 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
571 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
572 //RequestMapItemsCompleted(response);
573 Interlocked.Increment(ref nAsyncRequests); 611 Interlocked.Increment(ref nAsyncRequests);
612 Util.FireAndForget(x =>
613 {
614 RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
615 });
574 } 616 }
575 } 617 }
576 618
@@ -586,147 +628,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
586 Watchdog.RemoveThread(); 628 Watchdog.RemoveThread();
587 } 629 }
588 630
589 const int MAX_ASYNC_REQUESTS = 20;
590
591 /// <summary> 631 /// <summary>
592 /// Enqueues the map item request into the services throttle processing thread 632 /// Enqueues the map item request into the processing thread
593 /// </summary> 633 /// </summary>
594 /// <param name="state"></param> 634 /// <param name="state"></param>
595 public void EnqueueMapItemRequest(MapRequestState st) 635 public void EnqueueMapItemRequest(MapRequestState state)
596 {
597
598 m_ServiceThrottle.Enqueue("map-item", st.regionhandle.ToString() + st.agentID.ToString(), delegate
599 {
600 if (st.agentID != UUID.Zero)
601 {
602 bool dorequest = true;
603 lock (m_rootAgents)
604 {
605 if (!m_rootAgents.Contains(st.agentID))
606 dorequest = false;
607 }
608
609 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
610 {
611 if (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
612 {
613 // AH!!! Recursive !
614 // Put this request back in the queue and return
615 EnqueueMapItemRequest(st);
616 return;
617 }
618
619 RequestMapItemsDelegate d = RequestMapItemsAsync;
620 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
621 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
622 //RequestMapItemsCompleted(response);
623 Interlocked.Increment(ref nAsyncRequests);
624 }
625 }
626 });
627 }
628
629 /// <summary>
630 /// Sends the mapitem response to the IClientAPI
631 /// </summary>
632 /// <param name="response">The OSDMap Response for the mapitem</param>
633 private void RequestMapItemsCompleted(IAsyncResult iar)
634 { 636 {
635 AsyncResult result = (AsyncResult)iar; 637 lock (requests)
636 RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate;
637
638 OSDMap response = (OSDMap)icon.EndInvoke(iar);
639
640 Interlocked.Decrement(ref nAsyncRequests);
641
642 if (!response.ContainsKey("requestID"))
643 return;
644
645 UUID requestID = response["requestID"].AsUUID();
646
647 if (requestID != UUID.Zero)
648 { 638 {
649 MapRequestState mrs = new MapRequestState(); 639 queueEvent.Set();
650 mrs.agentID = UUID.Zero; 640 requests.Enqueue(state);
651 lock (m_openRequests)
652 {
653 if (m_openRequests.ContainsKey(requestID))
654 {
655 mrs = m_openRequests[requestID];
656 m_openRequests.Remove(requestID);
657 }
658 }
659
660 if (mrs.agentID != UUID.Zero)
661 {
662 ScenePresence av = null;
663 m_scene.TryGetScenePresence(mrs.agentID, out av);
664 if (av != null)
665 {
666 if (response.ContainsKey(mrs.itemtype.ToString()))
667 {
668 List<mapItemReply> returnitems = new List<mapItemReply>();
669 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()];
670 for (int i = 0; i < itemarray.Count; i++)
671 {
672 OSDMap mapitem = (OSDMap)itemarray[i];
673 mapItemReply mi = new mapItemReply();
674 mi.x = (uint)mapitem["X"].AsInteger();
675 mi.y = (uint)mapitem["Y"].AsInteger();
676 mi.id = mapitem["ID"].AsUUID();
677 mi.Extra = mapitem["Extra"].AsInteger();
678 mi.Extra2 = mapitem["Extra2"].AsInteger();
679 mi.name = mapitem["Name"].AsString();
680 returnitems.Add(mi);
681 }
682 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
683 }
684
685 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
686 uint itemtype = 7;
687
688 if (response.ContainsKey(itemtype.ToString()))
689 {
690 List<mapItemReply> returnitems = new List<mapItemReply>();
691 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
692 for (int i = 0; i < itemarray.Count; i++)
693 {
694 OSDMap mapitem = (OSDMap)itemarray[i];
695 mapItemReply mi = new mapItemReply();
696 mi.x = (uint)mapitem["X"].AsInteger();
697 mi.y = (uint)mapitem["Y"].AsInteger();
698 mi.id = mapitem["ID"].AsUUID();
699 mi.Extra = mapitem["Extra"].AsInteger();
700 mi.Extra2 = mapitem["Extra2"].AsInteger();
701 mi.name = mapitem["Name"].AsString();
702 returnitems.Add(mi);
703 }
704 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
705 }
706
707 // Service 1 (MAP_ITEM_TELEHUB)
708 itemtype = 1;
709
710 if (response.ContainsKey(itemtype.ToString()))
711 {
712 List<mapItemReply> returnitems = new List<mapItemReply>();
713 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
714 for (int i = 0; i < itemarray.Count; i++)
715 {
716 OSDMap mapitem = (OSDMap)itemarray[i];
717 mapItemReply mi = new mapItemReply();
718 mi.x = (uint)mapitem["X"].AsInteger();
719 mi.y = (uint)mapitem["Y"].AsInteger();
720 mi.id = mapitem["ID"].AsUUID();
721 mi.Extra = mapitem["Extra"].AsInteger();
722 mi.Extra2 = mapitem["Extra2"].AsInteger();
723 mi.name = mapitem["Name"].AsString();
724 returnitems.Add(mi);
725 }
726 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
727 }
728 }
729 }
730 } 641 }
731 } 642 }
732 643
@@ -753,8 +664,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
753 EnqueueMapItemRequest(st); 664 EnqueueMapItemRequest(st);
754 } 665 }
755 666
756 private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags,
757 uint EstateID, bool godlike, uint itemtype, ulong regionhandle);
758 /// <summary> 667 /// <summary>
759 /// Does the actual remote mapitem request 668 /// Does the actual remote mapitem request
760 /// This should be called from an asynchronous thread 669 /// This should be called from an asynchronous thread
@@ -769,7 +678,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
769 /// <param name="itemtype">passed in from packet</param> 678 /// <param name="itemtype">passed in from packet</param>
770 /// <param name="regionhandle">Region we're looking up</param> 679 /// <param name="regionhandle">Region we're looking up</param>
771 /// <returns></returns> 680 /// <returns></returns>
772 private OSDMap RequestMapItemsAsync(UUID id, uint flags, 681 private void RequestMapItemsAsync(UUID id, uint flags,
773 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 682 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
774 { 683 {
775// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 684// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
@@ -792,7 +701,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
792 } 701 }
793 702
794 if (blacklisted) 703 if (blacklisted)
795 return new OSDMap(); 704 {
705 Interlocked.Decrement(ref nAsyncRequests);
706 return;
707 }
796 708
797 UUID requestID = UUID.Random(); 709 UUID requestID = UUID.Random();
798 lock (m_cachedRegionMapItemsAddress) 710 lock (m_cachedRegionMapItemsAddress)
@@ -800,6 +712,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
800 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 712 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
801 httpserver = m_cachedRegionMapItemsAddress[regionhandle]; 713 httpserver = m_cachedRegionMapItemsAddress[regionhandle];
802 } 714 }
715
803 if (httpserver.Length == 0) 716 if (httpserver.Length == 0)
804 { 717 {
805 uint x = 0, y = 0; 718 uint x = 0, y = 0;
@@ -844,18 +757,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
844 757
845 // Can't find the http server 758 // Can't find the http server
846 if (httpserver.Length == 0 || blacklisted) 759 if (httpserver.Length == 0 || blacklisted)
847 return new OSDMap(); 760 {
848 761 Interlocked.Decrement(ref nAsyncRequests);
849 MapRequestState mrs = new MapRequestState(); 762 return;
850 mrs.agentID = id; 763 }
851 mrs.EstateID = EstateID;
852 mrs.flags = flags;
853 mrs.godlike = godlike;
854 mrs.itemtype=itemtype;
855 mrs.regionhandle = regionhandle;
856
857 lock (m_openRequests)
858 m_openRequests.Add(requestID, mrs);
859 764
860 WebRequest mapitemsrequest = null; 765 WebRequest mapitemsrequest = null;
861 try 766 try
@@ -865,7 +770,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
865 catch (Exception e) 770 catch (Exception e)
866 { 771 {
867 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); 772 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
868 return new OSDMap(); 773 Interlocked.Decrement(ref nAsyncRequests);
774 return;
869 } 775 }
870 776
871 mapitemsrequest.Method = "POST"; 777 mapitemsrequest.Method = "POST";
@@ -890,7 +796,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
890 catch (WebException ex) 796 catch (WebException ex)
891 { 797 {
892 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 798 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
893 responseMap["connect"] = OSD.FromBoolean(false);
894 lock (m_blacklistedurls) 799 lock (m_blacklistedurls)
895 { 800 {
896 if (!m_blacklistedurls.ContainsKey(httpserver)) 801 if (!m_blacklistedurls.ContainsKey(httpserver))
@@ -899,13 +804,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
899 804
900 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 805 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
901 806
902 return responseMap; 807 Interlocked.Decrement(ref nAsyncRequests);
808 return;
903 } 809 }
904 catch 810 catch
905 { 811 {
906 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 812 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
907 responseMap["connect"] = OSD.FromBoolean(false); 813 Interlocked.Decrement(ref nAsyncRequests);
908 return responseMap; 814 return;
909 } 815 }
910 finally 816 finally
911 { 817 {
@@ -914,26 +820,24 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
914 } 820 }
915 821
916 string response_mapItems_reply = null; 822 string response_mapItems_reply = null;
917 { 823 { // get the response
824 StreamReader sr = null;
918 try 825 try
919 { 826 {
920 using (WebResponse webResponse = mapitemsrequest.GetResponse()) 827 WebResponse webResponse = mapitemsrequest.GetResponse();
828 if (webResponse != null)
921 { 829 {
922 if (webResponse != null) 830 sr = new StreamReader(webResponse.GetResponseStream());
923 { 831 response_mapItems_reply = sr.ReadToEnd().Trim();
924 using (Stream s = webResponse.GetResponseStream()) 832 }
925 using (StreamReader sr = new StreamReader(s)) 833 else
926 response_mapItems_reply = sr.ReadToEnd().Trim(); 834 {
927 } 835 Interlocked.Decrement(ref nAsyncRequests);
928 else 836 return;
929 { 837 }
930 return new OSDMap();
931 }
932 }
933 } 838 }
934 catch (WebException) 839 catch (WebException)
935 { 840 {
936 responseMap["connect"] = OSD.FromBoolean(false);
937 lock (m_blacklistedurls) 841 lock (m_blacklistedurls)
938 { 842 {
939 if (!m_blacklistedurls.ContainsKey(httpserver)) 843 if (!m_blacklistedurls.ContainsKey(httpserver))
@@ -942,19 +846,25 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
942 846
943 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 847 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
944 848
945 return responseMap; 849 Interlocked.Decrement(ref nAsyncRequests);
850 return;
946 } 851 }
947 catch 852 catch
948 { 853 {
949 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 854 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
950 responseMap["connect"] = OSD.FromBoolean(false);
951 lock (m_blacklistedregions) 855 lock (m_blacklistedregions)
952 { 856 {
953 if (!m_blacklistedregions.ContainsKey(regionhandle)) 857 if (!m_blacklistedregions.ContainsKey(regionhandle))
954 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 858 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
955 } 859 }
956 860
957 return responseMap; 861 Interlocked.Decrement(ref nAsyncRequests);
862 return;
863 }
864 finally
865 {
866 if (sr != null)
867 sr.Close();
958 } 868 }
959 869
960 OSD rezResponse = null; 870 OSD rezResponse = null;
@@ -968,15 +878,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
968 catch (Exception ex) 878 catch (Exception ex)
969 { 879 {
970 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 880 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
971 responseMap["connect"] = OSD.FromBoolean(false);
972
973 lock (m_blacklistedregions) 881 lock (m_blacklistedregions)
974 { 882 {
975 if (!m_blacklistedregions.ContainsKey(regionhandle)) 883 if (!m_blacklistedregions.ContainsKey(regionhandle))
976 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 884 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
977 } 885 }
978 886
979 return responseMap; 887 Interlocked.Decrement(ref nAsyncRequests);
888 return;
980 } 889 }
981 } 890 }
982 891
@@ -990,7 +899,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
990 } 899 }
991 } 900 }
992 901
993 return responseMap; 902 Interlocked.Decrement(ref nAsyncRequests);
903
904 if (id != UUID.Zero)
905 {
906 ScenePresence av = null;
907 m_scene.TryGetScenePresence(id, out av);
908 if (av != null)
909 {
910 if (responseMap.ContainsKey(itemtype.ToString()))
911 {
912 List<mapItemReply> returnitems = new List<mapItemReply>();
913 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
914 for (int i = 0; i < itemarray.Count; i++)
915 {
916 OSDMap mapitem = (OSDMap)itemarray[i];
917 mapItemReply mi = new mapItemReply();
918 mi.x = (uint)mapitem["X"].AsInteger();
919 mi.y = (uint)mapitem["Y"].AsInteger();
920 mi.id = mapitem["ID"].AsUUID();
921 mi.Extra = mapitem["Extra"].AsInteger();
922 mi.Extra2 = mapitem["Extra2"].AsInteger();
923 mi.name = mapitem["Name"].AsString();
924 returnitems.Add(mi);
925 }
926 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
927 }
928
929 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
930 itemtype = 7;
931
932 if (responseMap.ContainsKey(itemtype.ToString()))
933 {
934 List<mapItemReply> returnitems = new List<mapItemReply>();
935 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
936 for (int i = 0; i < itemarray.Count; i++)
937 {
938 OSDMap mapitem = (OSDMap)itemarray[i];
939 mapItemReply mi = new mapItemReply();
940 mi.x = (uint)mapitem["X"].AsInteger();
941 mi.y = (uint)mapitem["Y"].AsInteger();
942 mi.id = mapitem["ID"].AsUUID();
943 mi.Extra = mapitem["Extra"].AsInteger();
944 mi.Extra2 = mapitem["Extra2"].AsInteger();
945 mi.name = mapitem["Name"].AsString();
946 returnitems.Add(mi);
947 }
948 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
949 }
950
951 // Service 1 (MAP_ITEM_TELEHUB)
952 itemtype = 1;
953
954 if (responseMap.ContainsKey(itemtype.ToString()))
955 {
956 List<mapItemReply> returnitems = new List<mapItemReply>();
957 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
958 for (int i = 0; i < itemarray.Count; i++)
959 {
960 OSDMap mapitem = (OSDMap)itemarray[i];
961 mapItemReply mi = new mapItemReply();
962 mi.x = (uint)mapitem["X"].AsInteger();
963 mi.y = (uint)mapitem["Y"].AsInteger();
964 mi.id = mapitem["ID"].AsUUID();
965 mi.Extra = mapitem["Extra"].AsInteger();
966 mi.Extra2 = mapitem["Extra2"].AsInteger();
967 mi.name = mapitem["Name"].AsString();
968 returnitems.Add(mi);
969 }
970 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
971 }
972 }
973 }
994 } 974 }
995 975
996 /// <summary> 976 /// <summary>
@@ -1000,7 +980,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1000 /// <param name="minY"></param> 980 /// <param name="minY"></param>
1001 /// <param name="maxX"></param> 981 /// <param name="maxX"></param>
1002 /// <param name="maxY"></param> 982 /// <param name="maxY"></param>
1003 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 983 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1004 { 984 {
1005 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); 985 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
1006 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible 986 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible
@@ -1053,21 +1033,91 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1053 1033
1054 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1034 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1055 { 1035 {
1036 MapBlockRequestData req = new MapBlockRequestData();
1037
1038 req.client = remoteClient;
1039 req.minX = minX;
1040 req.maxX = maxX;
1041 req.minY = minY;
1042 req.maxY = maxY;
1043 req.flags = flag;
1044
1045 lock (m_mapBlockRequestEvent)
1046 {
1047 if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId))
1048 m_mapBlockRequests[remoteClient.AgentId] = new Queue<MapBlockRequestData>();
1049 m_mapBlockRequests[remoteClient.AgentId].Enqueue(req);
1050 m_mapBlockRequestEvent.Set();
1051 }
1052
1053 return new List<MapBlockData>();
1054 }
1055
1056 protected void MapBlockSendThread()
1057 {
1058 while (true)
1059 {
1060 List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
1061
1062 m_mapBlockRequestEvent.WaitOne();
1063 lock (m_mapBlockRequestEvent)
1064 {
1065 int total = 0;
1066 foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
1067 {
1068 if (q.Count > 0)
1069 thisRunData.Add(q.Dequeue());
1070
1071 total += q.Count;
1072 }
1073
1074 if (total == 0)
1075 m_mapBlockRequestEvent.Reset();
1076 }
1077
1078 foreach (MapBlockRequestData req in thisRunData)
1079 {
1080 // Null client stops thread
1081 if (req.client == null)
1082 return;
1083
1084 GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
1085 }
1086
1087 Thread.Sleep(50);
1088 }
1089 }
1090
1091 protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1092 {
1093 List<MapBlockData> allBlocks = new List<MapBlockData>();
1056 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1094 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1057 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1095 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1058 (minX - 4) * (int)Constants.RegionSize, 1096 minX * (int)Constants.RegionSize,
1059 (maxX + 4) * (int)Constants.RegionSize, 1097 maxX * (int)Constants.RegionSize,
1060 (minY - 4) * (int)Constants.RegionSize, 1098 minY * (int)Constants.RegionSize,
1061 (maxY + 4) * (int)Constants.RegionSize); 1099 maxY * (int)Constants.RegionSize);
1100// (minX - 4) * (int)Constants.RegionSize,
1101// (maxX + 4) * (int)Constants.RegionSize,
1102// (minY - 4) * (int)Constants.RegionSize,
1103// (maxY + 4) * (int)Constants.RegionSize);
1062 foreach (GridRegion r in regions) 1104 foreach (GridRegion r in regions)
1063 { 1105 {
1064 MapBlockData block = new MapBlockData(); 1106 MapBlockData block = new MapBlockData();
1065 MapBlockFromGridRegion(block, r, flag); 1107 MapBlockFromGridRegion(block, r, flag);
1066 mapBlocks.Add(block); 1108 mapBlocks.Add(block);
1109 allBlocks.Add(block);
1110 if (mapBlocks.Count >= 10)
1111 {
1112 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1113 mapBlocks.Clear();
1114 Thread.Sleep(50);
1115 }
1067 } 1116 }
1068 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1117 if (mapBlocks.Count > 0)
1118 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1069 1119
1070 return mapBlocks; 1120 return allBlocks;
1071 } 1121 }
1072 1122
1073 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag) 1123 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
@@ -1301,7 +1351,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1301 } 1351 }
1302 else 1352 else
1303 { 1353 {
1304 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1354 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1305 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 1355 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
1306 { 1356 {
1307 OSDMap responsemapdata = new OSDMap(); 1357 OSDMap responsemapdata = new OSDMap();
@@ -1477,6 +1527,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1477 { 1527 {
1478 m_rootAgents.Remove(avatar.UUID); 1528 m_rootAgents.Remove(avatar.UUID);
1479 } 1529 }
1530
1531 lock (m_mapBlockRequestEvent)
1532 {
1533 if (m_mapBlockRequests.ContainsKey(avatar.UUID))
1534 m_mapBlockRequests.Remove(avatar.UUID);
1535 }
1480 } 1536 }
1481 1537
1482 public void OnRegionUp(GridRegion otherRegion) 1538 public void OnRegionUp(GridRegion otherRegion)
@@ -1521,9 +1577,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1521 Color background = Color.FromArgb(0, 0, 0, 0); 1577 Color background = Color.FromArgb(0, 0, 0, 0);
1522 SolidBrush transparent = new SolidBrush(background); 1578 SolidBrush transparent = new SolidBrush(background);
1523 Graphics g = Graphics.FromImage(overlay); 1579 Graphics g = Graphics.FromImage(overlay);
1524 g.FillRectangle(transparent, 0, 0, 256, 256); 1580 g.FillRectangle(transparent, 0, 0, 255, 255);
1525 1581
1526 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); 1582 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9));
1583 Pen grey = new Pen(Color.FromArgb(255, 92, 92, 92));
1527 1584
1528 foreach (ILandObject land in parcels) 1585 foreach (ILandObject land in parcels)
1529 { 1586 {
@@ -1531,8 +1588,42 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1531 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0) 1588 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1532 { 1589 {
1533 landForSale = true; 1590 landForSale = true;
1591
1592 bool[,] landBitmap = land.GetLandBitmap();
1593
1594 for (int x = 0 ; x < 64 ; x++)
1595 {
1596 for (int y = 0 ; y < 64 ; y++)
1597 {
1598 if (landBitmap[x, y])
1599 {
1600 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1601
1602 if (x > 0)
1603 {
1604 if ((saleBitmap[x - 1, y] || landBitmap[x - 1, y]) == false)
1605 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4, 255 - (y * 4));
1606 }
1607 if (y > 0)
1608 {
1609 if ((saleBitmap[x, y-1] || landBitmap[x, y-1]) == false)
1610 g.DrawLine(grey, x * 4, 255 - (y * 4), x * 4 + 3, 255 - (y * 4));
1611 }
1612 if (x < 63)
1613 {
1614 if ((saleBitmap[x + 1, y] || landBitmap[x + 1, y]) == false)
1615 g.DrawLine(grey, x * 4 + 3, 252 - (y * 4), x * 4 + 3, 255 - (y * 4));
1616 }
1617 if (y < 63)
1618 {
1619 if ((saleBitmap[x, y + 1] || landBitmap[x, y + 1]) == false)
1620 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4 + 3, 252 - (y * 4));
1621 }
1622 }
1623 }
1624 }
1534 1625
1535 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap()); 1626 saleBitmap = land.MergeLandBitmaps(saleBitmap, landBitmap);
1536 } 1627 }
1537 } 1628 }
1538 1629
@@ -1544,15 +1635,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1544 1635
1545 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName); 1636 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1546 1637
1547 for (int x = 0 ; x < 64 ; x++)
1548 {
1549 for (int y = 0 ; y < 64 ; y++)
1550 {
1551 if (saleBitmap[x, y])
1552 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1553 }
1554 }
1555
1556 try 1638 try
1557 { 1639 {
1558 return OpenJPEG.EncodeFromImage(overlay, true); 1640 return OpenJPEG.EncodeFromImage(overlay, true);
@@ -1574,4 +1656,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1574 public uint itemtype; 1656 public uint itemtype;
1575 public ulong regionhandle; 1657 public ulong regionhandle;
1576 } 1658 }
1659
1660 public struct MapBlockRequestData
1661 {
1662 public IClientAPI client;
1663 public int minX;
1664 public int minY;
1665 public int maxX;
1666 public int maxY;
1667 public uint flags;
1668 }
1577} 1669}