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 a26a5f0..bf18616 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
@@ -176,13 +173,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
176 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; 173 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent;
177 m_scene.EventManager.OnRegionUp += OnRegionUp; 174 m_scene.EventManager.OnRegionUp += OnRegionUp;
178 175
179// StartThread(new object()); 176 StartThread(new object());
180 } 177 }
181 178
182 // this has to be called with a lock on m_scene 179 // this has to be called with a lock on m_scene
183 protected virtual void RemoveHandlers() 180 protected virtual void RemoveHandlers()
184 { 181 {
185// StopThread(); 182 StopThread();
186 183
187 m_scene.EventManager.OnRegionUp -= OnRegionUp; 184 m_scene.EventManager.OnRegionUp -= OnRegionUp;
188 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent; 185 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent;
@@ -240,54 +237,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
240 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is 237 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
241 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. 238 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
242 239
243 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) 240 //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
244 { 241 //{
245 ScenePresence avatarPresence = null; 242 // ScenePresence avatarPresence = null;
246 243
247 m_scene.TryGetScenePresence(agentID, out avatarPresence); 244 // m_scene.TryGetScenePresence(agentID, out avatarPresence);
248 245
249 if (avatarPresence != null) 246 // if (avatarPresence != null)
250 { 247 // {
251 bool lookup = false; 248 // bool lookup = false;
252 249
253 lock (cachedMapBlocks) 250 // lock (cachedMapBlocks)
254 { 251 // {
255 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) 252 // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
256 { 253 // {
257 List<MapBlockData> mapBlocks; 254 // List<MapBlockData> mapBlocks;
258 255
259 mapBlocks = cachedMapBlocks; 256 // mapBlocks = cachedMapBlocks;
260 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 257 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
261 } 258 // }
262 else 259 // else
263 { 260 // {
264 lookup = true; 261 // lookup = true;
265 } 262 // }
266 } 263 // }
267 if (lookup) 264 // if (lookup)
268 { 265 // {
269 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 266 // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
270 267
271 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 268 // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
272 (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, 269 // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
273 (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, 270 // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
274 (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, 271 // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
275 (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); 272 // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
276 foreach (GridRegion r in regions) 273 // foreach (GridRegion r in regions)
277 { 274 // {
278 MapBlockData block = new MapBlockData(); 275 // MapBlockData block = new MapBlockData();
279 MapBlockFromGridRegion(block, r, 0); 276 // MapBlockFromGridRegion(block, r, 0);
280 mapBlocks.Add(block); 277 // mapBlocks.Add(block);
281 } 278 // }
282 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 279 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
283 280
284 lock (cachedMapBlocks) 281 // lock (cachedMapBlocks)
285 cachedMapBlocks = mapBlocks; 282 // cachedMapBlocks = mapBlocks;
286 283
287 cachedTime = Util.UnixTimeSinceEpoch(); 284 // cachedTime = Util.UnixTimeSinceEpoch();
288 } 285 // }
289 } 286 // }
290 } 287 //}
291 288
292 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 289 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
293 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 290 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@@ -314,8 +311,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
314 protected static OSDMapLayer GetOSDMapLayerResponse() 311 protected static OSDMapLayer GetOSDMapLayerResponse()
315 { 312 {
316 OSDMapLayer mapLayer = new OSDMapLayer(); 313 OSDMapLayer mapLayer = new OSDMapLayer();
317 mapLayer.Right = 5000; 314 mapLayer.Right = 2048;
318 mapLayer.Top = 5000; 315 mapLayer.Top = 2048;
319 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); 316 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
320 317
321 return mapLayer; 318 return mapLayer;
@@ -344,6 +341,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
344 { 341 {
345 m_rootAgents.Remove(AgentId); 342 m_rootAgents.Remove(AgentId);
346 } 343 }
344 lock (m_mapBlockRequestEvent)
345 {
346 if (m_mapBlockRequests.ContainsKey(AgentId))
347 m_mapBlockRequests.Remove(AgentId);
348 }
347 } 349 }
348 #endregion 350 #endregion
349 351
@@ -366,6 +368,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
366 ThreadPriority.BelowNormal, 368 ThreadPriority.BelowNormal,
367 true, 369 true,
368 true); 370 true);
371 Watchdog.StartThread(
372 MapBlockSendThread,
373 string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
374 ThreadPriority.BelowNormal,
375 true,
376 true);
369 } 377 }
370 378
371 /// <summary> 379 /// <summary>
@@ -381,7 +389,27 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
381 st.itemtype=0; 389 st.itemtype=0;
382 st.regionhandle=0; 390 st.regionhandle=0;
383 391
384 requests.Enqueue(st); 392 lock (requests)
393 {
394 queueEvent.Set();
395 requests.Enqueue(st);
396 }
397
398 MapBlockRequestData req = new MapBlockRequestData();
399
400 req.client = null;
401 req.minX = 0;
402 req.maxX = 0;
403 req.minY = 0;
404 req.maxY = 0;
405 req.flags = 0;
406
407 lock (m_mapBlockRequestEvent)
408 {
409 m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
410 m_mapBlockRequests[UUID.Zero].Enqueue(req);
411 m_mapBlockRequestEvent.Set();
412 }
385 } 413 }
386 414
387 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 415 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -532,12 +560,26 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
532 /// </summary> 560 /// </summary>
533 public void process() 561 public void process()
534 { 562 {
535 //const int MAX_ASYNC_REQUESTS = 20; 563 const int MAX_ASYNC_REQUESTS = 20;
536 try 564 try
537 { 565 {
538 while (true) 566 while (true)
539 { 567 {
540 MapRequestState st = requests.Dequeue(1000); 568 MapRequestState st = new MapRequestState();
569 bool valid = false;
570 queueEvent.WaitOne();
571 lock (requests)
572 {
573 if (requests.Count > 0)
574 {
575 st = requests.Dequeue();
576 valid = true;
577 }
578 if (requests.Count == 0)
579 queueEvent.Reset();
580 }
581 if (!valid)
582 continue;
541 583
542 // end gracefully 584 // end gracefully
543 if (st.agentID == STOP_UUID) 585 if (st.agentID == STOP_UUID)
@@ -555,13 +597,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
555 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 597 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
556 { 598 {
557 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 599 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
558 Thread.Sleep(80); 600 Thread.Sleep(100);
559 601
560 RequestMapItemsDelegate d = RequestMapItemsAsync;
561 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
562 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
563 //RequestMapItemsCompleted(response);
564 Interlocked.Increment(ref nAsyncRequests); 602 Interlocked.Increment(ref nAsyncRequests);
603 Util.FireAndForget(x =>
604 {
605 RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
606 });
565 } 607 }
566 } 608 }
567 609
@@ -577,147 +619,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
577 Watchdog.RemoveThread(); 619 Watchdog.RemoveThread();
578 } 620 }
579 621
580 const int MAX_ASYNC_REQUESTS = 20;
581
582 /// <summary> 622 /// <summary>
583 /// Enqueues the map item request into the services throttle processing thread 623 /// Enqueues the map item request into the processing thread
584 /// </summary> 624 /// </summary>
585 /// <param name="state"></param> 625 /// <param name="state"></param>
586 public void EnqueueMapItemRequest(MapRequestState st) 626 public void EnqueueMapItemRequest(MapRequestState state)
587 {
588
589 m_ServiceThrottle.Enqueue("map-item", st.regionhandle.ToString() + st.agentID.ToString(), delegate
590 {
591 if (st.agentID != UUID.Zero)
592 {
593 bool dorequest = true;
594 lock (m_rootAgents)
595 {
596 if (!m_rootAgents.Contains(st.agentID))
597 dorequest = false;
598 }
599
600 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
601 {
602 if (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
603 {
604 // AH!!! Recursive !
605 // Put this request back in the queue and return
606 EnqueueMapItemRequest(st);
607 return;
608 }
609
610 RequestMapItemsDelegate d = RequestMapItemsAsync;
611 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
612 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
613 //RequestMapItemsCompleted(response);
614 Interlocked.Increment(ref nAsyncRequests);
615 }
616 }
617 });
618 }
619
620 /// <summary>
621 /// Sends the mapitem response to the IClientAPI
622 /// </summary>
623 /// <param name="response">The OSDMap Response for the mapitem</param>
624 private void RequestMapItemsCompleted(IAsyncResult iar)
625 { 627 {
626 AsyncResult result = (AsyncResult)iar; 628 lock (requests)
627 RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate;
628
629 OSDMap response = (OSDMap)icon.EndInvoke(iar);
630
631 Interlocked.Decrement(ref nAsyncRequests);
632
633 if (!response.ContainsKey("requestID"))
634 return;
635
636 UUID requestID = response["requestID"].AsUUID();
637
638 if (requestID != UUID.Zero)
639 { 629 {
640 MapRequestState mrs = new MapRequestState(); 630 queueEvent.Set();
641 mrs.agentID = UUID.Zero; 631 requests.Enqueue(state);
642 lock (m_openRequests)
643 {
644 if (m_openRequests.ContainsKey(requestID))
645 {
646 mrs = m_openRequests[requestID];
647 m_openRequests.Remove(requestID);
648 }
649 }
650
651 if (mrs.agentID != UUID.Zero)
652 {
653 ScenePresence av = null;
654 m_scene.TryGetScenePresence(mrs.agentID, out av);
655 if (av != null)
656 {
657 if (response.ContainsKey(mrs.itemtype.ToString()))
658 {
659 List<mapItemReply> returnitems = new List<mapItemReply>();
660 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()];
661 for (int i = 0; i < itemarray.Count; i++)
662 {
663 OSDMap mapitem = (OSDMap)itemarray[i];
664 mapItemReply mi = new mapItemReply();
665 mi.x = (uint)mapitem["X"].AsInteger();
666 mi.y = (uint)mapitem["Y"].AsInteger();
667 mi.id = mapitem["ID"].AsUUID();
668 mi.Extra = mapitem["Extra"].AsInteger();
669 mi.Extra2 = mapitem["Extra2"].AsInteger();
670 mi.name = mapitem["Name"].AsString();
671 returnitems.Add(mi);
672 }
673 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
674 }
675
676 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
677 uint itemtype = 7;
678
679 if (response.ContainsKey(itemtype.ToString()))
680 {
681 List<mapItemReply> returnitems = new List<mapItemReply>();
682 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
683 for (int i = 0; i < itemarray.Count; i++)
684 {
685 OSDMap mapitem = (OSDMap)itemarray[i];
686 mapItemReply mi = new mapItemReply();
687 mi.x = (uint)mapitem["X"].AsInteger();
688 mi.y = (uint)mapitem["Y"].AsInteger();
689 mi.id = mapitem["ID"].AsUUID();
690 mi.Extra = mapitem["Extra"].AsInteger();
691 mi.Extra2 = mapitem["Extra2"].AsInteger();
692 mi.name = mapitem["Name"].AsString();
693 returnitems.Add(mi);
694 }
695 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
696 }
697
698 // Service 1 (MAP_ITEM_TELEHUB)
699 itemtype = 1;
700
701 if (response.ContainsKey(itemtype.ToString()))
702 {
703 List<mapItemReply> returnitems = new List<mapItemReply>();
704 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
705 for (int i = 0; i < itemarray.Count; i++)
706 {
707 OSDMap mapitem = (OSDMap)itemarray[i];
708 mapItemReply mi = new mapItemReply();
709 mi.x = (uint)mapitem["X"].AsInteger();
710 mi.y = (uint)mapitem["Y"].AsInteger();
711 mi.id = mapitem["ID"].AsUUID();
712 mi.Extra = mapitem["Extra"].AsInteger();
713 mi.Extra2 = mapitem["Extra2"].AsInteger();
714 mi.name = mapitem["Name"].AsString();
715 returnitems.Add(mi);
716 }
717 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
718 }
719 }
720 }
721 } 632 }
722 } 633 }
723 634
@@ -744,8 +655,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
744 EnqueueMapItemRequest(st); 655 EnqueueMapItemRequest(st);
745 } 656 }
746 657
747 private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags,
748 uint EstateID, bool godlike, uint itemtype, ulong regionhandle);
749 /// <summary> 658 /// <summary>
750 /// Does the actual remote mapitem request 659 /// Does the actual remote mapitem request
751 /// This should be called from an asynchronous thread 660 /// This should be called from an asynchronous thread
@@ -760,7 +669,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
760 /// <param name="itemtype">passed in from packet</param> 669 /// <param name="itemtype">passed in from packet</param>
761 /// <param name="regionhandle">Region we're looking up</param> 670 /// <param name="regionhandle">Region we're looking up</param>
762 /// <returns></returns> 671 /// <returns></returns>
763 private OSDMap RequestMapItemsAsync(UUID id, uint flags, 672 private void RequestMapItemsAsync(UUID id, uint flags,
764 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 673 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
765 { 674 {
766// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 675// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
@@ -783,7 +692,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
783 } 692 }
784 693
785 if (blacklisted) 694 if (blacklisted)
786 return new OSDMap(); 695 {
696 Interlocked.Decrement(ref nAsyncRequests);
697 return;
698 }
787 699
788 UUID requestID = UUID.Random(); 700 UUID requestID = UUID.Random();
789 lock (m_cachedRegionMapItemsAddress) 701 lock (m_cachedRegionMapItemsAddress)
@@ -791,6 +703,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
791 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 703 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
792 httpserver = m_cachedRegionMapItemsAddress[regionhandle]; 704 httpserver = m_cachedRegionMapItemsAddress[regionhandle];
793 } 705 }
706
794 if (httpserver.Length == 0) 707 if (httpserver.Length == 0)
795 { 708 {
796 uint x = 0, y = 0; 709 uint x = 0, y = 0;
@@ -835,18 +748,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
835 748
836 // Can't find the http server 749 // Can't find the http server
837 if (httpserver.Length == 0 || blacklisted) 750 if (httpserver.Length == 0 || blacklisted)
838 return new OSDMap(); 751 {
839 752 Interlocked.Decrement(ref nAsyncRequests);
840 MapRequestState mrs = new MapRequestState(); 753 return;
841 mrs.agentID = id; 754 }
842 mrs.EstateID = EstateID;
843 mrs.flags = flags;
844 mrs.godlike = godlike;
845 mrs.itemtype=itemtype;
846 mrs.regionhandle = regionhandle;
847
848 lock (m_openRequests)
849 m_openRequests.Add(requestID, mrs);
850 755
851 WebRequest mapitemsrequest = null; 756 WebRequest mapitemsrequest = null;
852 try 757 try
@@ -856,7 +761,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
856 catch (Exception e) 761 catch (Exception e)
857 { 762 {
858 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); 763 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
859 return new OSDMap(); 764 Interlocked.Decrement(ref nAsyncRequests);
765 return;
860 } 766 }
861 767
862 mapitemsrequest.Method = "POST"; 768 mapitemsrequest.Method = "POST";
@@ -881,7 +787,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
881 catch (WebException ex) 787 catch (WebException ex)
882 { 788 {
883 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 789 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
884 responseMap["connect"] = OSD.FromBoolean(false);
885 lock (m_blacklistedurls) 790 lock (m_blacklistedurls)
886 { 791 {
887 if (!m_blacklistedurls.ContainsKey(httpserver)) 792 if (!m_blacklistedurls.ContainsKey(httpserver))
@@ -890,13 +795,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
890 795
891 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 796 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
892 797
893 return responseMap; 798 Interlocked.Decrement(ref nAsyncRequests);
799 return;
894 } 800 }
895 catch 801 catch
896 { 802 {
897 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 803 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
898 responseMap["connect"] = OSD.FromBoolean(false); 804 Interlocked.Decrement(ref nAsyncRequests);
899 return responseMap; 805 return;
900 } 806 }
901 finally 807 finally
902 { 808 {
@@ -905,26 +811,24 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
905 } 811 }
906 812
907 string response_mapItems_reply = null; 813 string response_mapItems_reply = null;
908 { 814 { // get the response
815 StreamReader sr = null;
909 try 816 try
910 { 817 {
911 using (WebResponse webResponse = mapitemsrequest.GetResponse()) 818 WebResponse webResponse = mapitemsrequest.GetResponse();
819 if (webResponse != null)
912 { 820 {
913 if (webResponse != null) 821 sr = new StreamReader(webResponse.GetResponseStream());
914 { 822 response_mapItems_reply = sr.ReadToEnd().Trim();
915 using (Stream s = webResponse.GetResponseStream()) 823 }
916 using (StreamReader sr = new StreamReader(s)) 824 else
917 response_mapItems_reply = sr.ReadToEnd().Trim(); 825 {
918 } 826 Interlocked.Decrement(ref nAsyncRequests);
919 else 827 return;
920 { 828 }
921 return new OSDMap();
922 }
923 }
924 } 829 }
925 catch (WebException) 830 catch (WebException)
926 { 831 {
927 responseMap["connect"] = OSD.FromBoolean(false);
928 lock (m_blacklistedurls) 832 lock (m_blacklistedurls)
929 { 833 {
930 if (!m_blacklistedurls.ContainsKey(httpserver)) 834 if (!m_blacklistedurls.ContainsKey(httpserver))
@@ -933,19 +837,25 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
933 837
934 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 838 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
935 839
936 return responseMap; 840 Interlocked.Decrement(ref nAsyncRequests);
841 return;
937 } 842 }
938 catch 843 catch
939 { 844 {
940 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 845 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
941 responseMap["connect"] = OSD.FromBoolean(false);
942 lock (m_blacklistedregions) 846 lock (m_blacklistedregions)
943 { 847 {
944 if (!m_blacklistedregions.ContainsKey(regionhandle)) 848 if (!m_blacklistedregions.ContainsKey(regionhandle))
945 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 849 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
946 } 850 }
947 851
948 return responseMap; 852 Interlocked.Decrement(ref nAsyncRequests);
853 return;
854 }
855 finally
856 {
857 if (sr != null)
858 sr.Close();
949 } 859 }
950 860
951 OSD rezResponse = null; 861 OSD rezResponse = null;
@@ -959,15 +869,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
959 catch (Exception ex) 869 catch (Exception ex)
960 { 870 {
961 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 871 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
962 responseMap["connect"] = OSD.FromBoolean(false);
963
964 lock (m_blacklistedregions) 872 lock (m_blacklistedregions)
965 { 873 {
966 if (!m_blacklistedregions.ContainsKey(regionhandle)) 874 if (!m_blacklistedregions.ContainsKey(regionhandle))
967 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 875 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
968 } 876 }
969 877
970 return responseMap; 878 Interlocked.Decrement(ref nAsyncRequests);
879 return;
971 } 880 }
972 } 881 }
973 882
@@ -981,7 +890,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
981 } 890 }
982 } 891 }
983 892
984 return responseMap; 893 Interlocked.Decrement(ref nAsyncRequests);
894
895 if (id != UUID.Zero)
896 {
897 ScenePresence av = null;
898 m_scene.TryGetScenePresence(id, out av);
899 if (av != null)
900 {
901 if (responseMap.ContainsKey(itemtype.ToString()))
902 {
903 List<mapItemReply> returnitems = new List<mapItemReply>();
904 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
905 for (int i = 0; i < itemarray.Count; i++)
906 {
907 OSDMap mapitem = (OSDMap)itemarray[i];
908 mapItemReply mi = new mapItemReply();
909 mi.x = (uint)mapitem["X"].AsInteger();
910 mi.y = (uint)mapitem["Y"].AsInteger();
911 mi.id = mapitem["ID"].AsUUID();
912 mi.Extra = mapitem["Extra"].AsInteger();
913 mi.Extra2 = mapitem["Extra2"].AsInteger();
914 mi.name = mapitem["Name"].AsString();
915 returnitems.Add(mi);
916 }
917 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
918 }
919
920 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
921 itemtype = 7;
922
923 if (responseMap.ContainsKey(itemtype.ToString()))
924 {
925 List<mapItemReply> returnitems = new List<mapItemReply>();
926 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
927 for (int i = 0; i < itemarray.Count; i++)
928 {
929 OSDMap mapitem = (OSDMap)itemarray[i];
930 mapItemReply mi = new mapItemReply();
931 mi.x = (uint)mapitem["X"].AsInteger();
932 mi.y = (uint)mapitem["Y"].AsInteger();
933 mi.id = mapitem["ID"].AsUUID();
934 mi.Extra = mapitem["Extra"].AsInteger();
935 mi.Extra2 = mapitem["Extra2"].AsInteger();
936 mi.name = mapitem["Name"].AsString();
937 returnitems.Add(mi);
938 }
939 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
940 }
941
942 // Service 1 (MAP_ITEM_TELEHUB)
943 itemtype = 1;
944
945 if (responseMap.ContainsKey(itemtype.ToString()))
946 {
947 List<mapItemReply> returnitems = new List<mapItemReply>();
948 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
949 for (int i = 0; i < itemarray.Count; i++)
950 {
951 OSDMap mapitem = (OSDMap)itemarray[i];
952 mapItemReply mi = new mapItemReply();
953 mi.x = (uint)mapitem["X"].AsInteger();
954 mi.y = (uint)mapitem["Y"].AsInteger();
955 mi.id = mapitem["ID"].AsUUID();
956 mi.Extra = mapitem["Extra"].AsInteger();
957 mi.Extra2 = mapitem["Extra2"].AsInteger();
958 mi.name = mapitem["Name"].AsString();
959 returnitems.Add(mi);
960 }
961 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
962 }
963 }
964 }
985 } 965 }
986 966
987 /// <summary> 967 /// <summary>
@@ -991,7 +971,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
991 /// <param name="minY"></param> 971 /// <param name="minY"></param>
992 /// <param name="maxX"></param> 972 /// <param name="maxX"></param>
993 /// <param name="maxY"></param> 973 /// <param name="maxY"></param>
994 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 974 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
995 { 975 {
996 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); 976 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
997 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible 977 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible
@@ -1044,21 +1024,91 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1044 1024
1045 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1025 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1046 { 1026 {
1027 MapBlockRequestData req = new MapBlockRequestData();
1028
1029 req.client = remoteClient;
1030 req.minX = minX;
1031 req.maxX = maxX;
1032 req.minY = minY;
1033 req.maxY = maxY;
1034 req.flags = flag;
1035
1036 lock (m_mapBlockRequestEvent)
1037 {
1038 if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId))
1039 m_mapBlockRequests[remoteClient.AgentId] = new Queue<MapBlockRequestData>();
1040 m_mapBlockRequests[remoteClient.AgentId].Enqueue(req);
1041 m_mapBlockRequestEvent.Set();
1042 }
1043
1044 return new List<MapBlockData>();
1045 }
1046
1047 protected void MapBlockSendThread()
1048 {
1049 while (true)
1050 {
1051 List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
1052
1053 m_mapBlockRequestEvent.WaitOne();
1054 lock (m_mapBlockRequestEvent)
1055 {
1056 int total = 0;
1057 foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
1058 {
1059 if (q.Count > 0)
1060 thisRunData.Add(q.Dequeue());
1061
1062 total += q.Count;
1063 }
1064
1065 if (total == 0)
1066 m_mapBlockRequestEvent.Reset();
1067 }
1068
1069 foreach (MapBlockRequestData req in thisRunData)
1070 {
1071 // Null client stops thread
1072 if (req.client == null)
1073 return;
1074
1075 GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
1076 }
1077
1078 Thread.Sleep(50);
1079 }
1080 }
1081
1082 protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1083 {
1084 List<MapBlockData> allBlocks = new List<MapBlockData>();
1047 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1085 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1048 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1086 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1049 (minX - 4) * (int)Constants.RegionSize, 1087 minX * (int)Constants.RegionSize,
1050 (maxX + 4) * (int)Constants.RegionSize, 1088 maxX * (int)Constants.RegionSize,
1051 (minY - 4) * (int)Constants.RegionSize, 1089 minY * (int)Constants.RegionSize,
1052 (maxY + 4) * (int)Constants.RegionSize); 1090 maxY * (int)Constants.RegionSize);
1091// (minX - 4) * (int)Constants.RegionSize,
1092// (maxX + 4) * (int)Constants.RegionSize,
1093// (minY - 4) * (int)Constants.RegionSize,
1094// (maxY + 4) * (int)Constants.RegionSize);
1053 foreach (GridRegion r in regions) 1095 foreach (GridRegion r in regions)
1054 { 1096 {
1055 MapBlockData block = new MapBlockData(); 1097 MapBlockData block = new MapBlockData();
1056 MapBlockFromGridRegion(block, r, flag); 1098 MapBlockFromGridRegion(block, r, flag);
1057 mapBlocks.Add(block); 1099 mapBlocks.Add(block);
1100 allBlocks.Add(block);
1101 if (mapBlocks.Count >= 10)
1102 {
1103 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1104 mapBlocks.Clear();
1105 Thread.Sleep(50);
1106 }
1058 } 1107 }
1059 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1108 if (mapBlocks.Count > 0)
1109 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1060 1110
1061 return mapBlocks; 1111 return allBlocks;
1062 } 1112 }
1063 1113
1064 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag) 1114 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
@@ -1282,7 +1332,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1282 } 1332 }
1283 else 1333 else
1284 { 1334 {
1285 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1335 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1286 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 1336 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
1287 { 1337 {
1288 OSDMap responsemapdata = new OSDMap(); 1338 OSDMap responsemapdata = new OSDMap();
@@ -1458,6 +1508,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1458 { 1508 {
1459 m_rootAgents.Remove(avatar.UUID); 1509 m_rootAgents.Remove(avatar.UUID);
1460 } 1510 }
1511
1512 lock (m_mapBlockRequestEvent)
1513 {
1514 if (m_mapBlockRequests.ContainsKey(avatar.UUID))
1515 m_mapBlockRequests.Remove(avatar.UUID);
1516 }
1461 } 1517 }
1462 1518
1463 public void OnRegionUp(GridRegion otherRegion) 1519 public void OnRegionUp(GridRegion otherRegion)
@@ -1502,9 +1558,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1502 Color background = Color.FromArgb(0, 0, 0, 0); 1558 Color background = Color.FromArgb(0, 0, 0, 0);
1503 SolidBrush transparent = new SolidBrush(background); 1559 SolidBrush transparent = new SolidBrush(background);
1504 Graphics g = Graphics.FromImage(overlay); 1560 Graphics g = Graphics.FromImage(overlay);
1505 g.FillRectangle(transparent, 0, 0, 256, 256); 1561 g.FillRectangle(transparent, 0, 0, 255, 255);
1506 1562
1507 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); 1563 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9));
1564 Pen grey = new Pen(Color.FromArgb(255, 92, 92, 92));
1508 1565
1509 foreach (ILandObject land in parcels) 1566 foreach (ILandObject land in parcels)
1510 { 1567 {
@@ -1512,8 +1569,42 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1512 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0) 1569 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1513 { 1570 {
1514 landForSale = true; 1571 landForSale = true;
1572
1573 bool[,] landBitmap = land.GetLandBitmap();
1574
1575 for (int x = 0 ; x < 64 ; x++)
1576 {
1577 for (int y = 0 ; y < 64 ; y++)
1578 {
1579 if (landBitmap[x, y])
1580 {
1581 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1582
1583 if (x > 0)
1584 {
1585 if ((saleBitmap[x - 1, y] || landBitmap[x - 1, y]) == false)
1586 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4, 255 - (y * 4));
1587 }
1588 if (y > 0)
1589 {
1590 if ((saleBitmap[x, y-1] || landBitmap[x, y-1]) == false)
1591 g.DrawLine(grey, x * 4, 255 - (y * 4), x * 4 + 3, 255 - (y * 4));
1592 }
1593 if (x < 63)
1594 {
1595 if ((saleBitmap[x + 1, y] || landBitmap[x + 1, y]) == false)
1596 g.DrawLine(grey, x * 4 + 3, 252 - (y * 4), x * 4 + 3, 255 - (y * 4));
1597 }
1598 if (y < 63)
1599 {
1600 if ((saleBitmap[x, y + 1] || landBitmap[x, y + 1]) == false)
1601 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4 + 3, 252 - (y * 4));
1602 }
1603 }
1604 }
1605 }
1515 1606
1516 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap()); 1607 saleBitmap = land.MergeLandBitmaps(saleBitmap, landBitmap);
1517 } 1608 }
1518 } 1609 }
1519 1610
@@ -1525,15 +1616,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1525 1616
1526 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName); 1617 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1527 1618
1528 for (int x = 0 ; x < 64 ; x++)
1529 {
1530 for (int y = 0 ; y < 64 ; y++)
1531 {
1532 if (saleBitmap[x, y])
1533 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1534 }
1535 }
1536
1537 try 1619 try
1538 { 1620 {
1539 return OpenJPEG.EncodeFromImage(overlay, true); 1621 return OpenJPEG.EncodeFromImage(overlay, true);
@@ -1555,4 +1637,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1555 public uint itemtype; 1637 public uint itemtype;
1556 public ulong regionhandle; 1638 public ulong regionhandle;
1557 } 1639 }
1640
1641 public struct MapBlockRequestData
1642 {
1643 public IClientAPI client;
1644 public int minX;
1645 public int minY;
1646 public int maxX;
1647 public int maxY;
1648 public uint flags;
1649 }
1558} 1650}