aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs456
2 files changed, 196 insertions, 269 deletions
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index 3a0bdc3..7370156 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
147 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4)) 147 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
148 { 148 {
149 // final block, closing the search result 149 // final block, closing the search result
150 AddFinalBlock(blocks); 150 AddFinalBlock(blocks,mapName);
151 151
152 // flags are agent flags sent from the viewer. 152 // flags are agent flags sent from the viewer.
153 // they have different values depending on different viewers, apparently 153 // they have different values depending on different viewers, apparently
@@ -211,8 +211,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
211 } 211 }
212 212
213 // final block, closing the search result 213 // final block, closing the search result
214 if(blocks.Count == 0) 214 AddFinalBlock(blocks,mapNameOrig);
215 AddFinalBlock(blocks);
216 215
217 // flags are agent flags sent from the viewer. 216 // flags are agent flags sent from the viewer.
218 // they have different values depending on different viewers, apparently 217 // they have different values depending on different viewers, apparently
@@ -231,14 +230,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
231 }); 230 });
232 } 231 }
233 232
234 private void AddFinalBlock(List<MapBlockData> blocks) 233 private void AddFinalBlock(List<MapBlockData> blocks,string name)
235 { 234 {
236 // final block, closing the search result 235 // final block, closing the search result
237 MapBlockData data = new MapBlockData(); 236 MapBlockData data = new MapBlockData();
238 data.Agents = 0; 237 data.Agents = 0;
239 data.Access = (byte)SimAccess.NonExistent; 238 data.Access = (byte)SimAccess.NonExistent;
240 data.MapImageId = UUID.Zero; 239 data.MapImageId = UUID.Zero;
241 data.Name = ""; 240 data.Name = name;
242 data.RegionFlags = 0; 241 data.RegionFlags = 0;
243 data.WaterHeight = 0; // not used 242 data.WaterHeight = 0; // not used
244 data.X = 0; 243 data.X = 0;
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 4c2751f..66811de 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -68,9 +68,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
68 private static readonly UUID STOP_UUID = UUID.Random(); 68 private static readonly UUID STOP_UUID = UUID.Random();
69 private static readonly string m_mapLayerPath = "0001/"; 69 private static readonly string m_mapLayerPath = "0001/";
70 70
71 private ManualResetEvent queueEvent = new ManualResetEvent(false); 71 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
72 private Queue<MapRequestState> requests = new Queue<MapRequestState>(); 72
73
74 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false); 73 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
75 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>(); 74 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
76 75
@@ -79,16 +78,19 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
79 78
80 protected Scene m_scene; 79 protected Scene m_scene;
81 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 80 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
82 private int cachedTime = 0;
83 private int blacklistTimeout = 10 * 60 * 1000; // 10 minutes
84 private byte[] myMapImageJPEG; 81 private byte[] myMapImageJPEG;
85 protected volatile bool m_Enabled = false; 82 protected volatile bool m_Enabled = false;
86 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); 83 private ExpiringCache<string, int> m_blacklistedurls = new ExpiringCache<string, int>();
87 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 84 private ExpiringCache<ulong, int> m_blacklistedregions = new ExpiringCache<ulong, int>();
88 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 85 private ExpiringCache<ulong, string> m_cachedRegionMapItemsAddress = new ExpiringCache<ulong, string>();
86 private ExpiringCache<ulong, OSDMap> m_cachedRegionMapItemsResponses =
87 new ExpiringCache<ulong, OSDMap>();
89 private List<UUID> m_rootAgents = new List<UUID>(); 88 private List<UUID> m_rootAgents = new List<UUID>();
90 private volatile bool threadrunning = false; 89 private volatile bool threadrunning = false;
91 90 // expire time for the blacklists in seconds
91 private double expireBlackListTime = 600.0; // 10 minutes
92 // expire mapItems responses time in seconds. If too high disturbs the green dots updates
93 private const double expireResponsesTime = 120.0; // 2 minutes ?
92 //private int CacheRegionsDistance = 256; 94 //private int CacheRegionsDistance = 256;
93 95
94 #region INonSharedRegionModule Members 96 #region INonSharedRegionModule Members
@@ -100,8 +102,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
100 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap") 102 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
101 m_Enabled = true; 103 m_Enabled = true;
102 104
103 blacklistTimeout 105 expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60);
104 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
105 } 106 }
106 107
107 public virtual void AddRegion(Scene scene) 108 public virtual void AddRegion(Scene scene)
@@ -245,6 +246,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
245 public string MapLayerRequest(string request, string path, string param, 246 public string MapLayerRequest(string request, string path, string param,
246 UUID agentID, Caps caps) 247 UUID agentID, Caps caps)
247 { 248 {
249 // not sure about this....
250
248 //try 251 //try
249 // 252 //
250 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", 253 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
@@ -333,6 +336,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
333 /// <returns></returns> 336 /// <returns></returns>
334 protected static OSDMapLayer GetOSDMapLayerResponse() 337 protected static OSDMapLayer GetOSDMapLayerResponse()
335 { 338 {
339 // not sure about this.... 2048 or master 5000 and hack above?
340
336 OSDMapLayer mapLayer = new OSDMapLayer(); 341 OSDMapLayer mapLayer = new OSDMapLayer();
337 mapLayer.Right = 2048; 342 mapLayer.Right = 2048;
338 mapLayer.Top = 2048; 343 mapLayer.Top = 2048;
@@ -412,11 +417,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
412 st.itemtype = 0; 417 st.itemtype = 0;
413 st.regionhandle = 0; 418 st.regionhandle = 0;
414 419
415 lock (requests) 420 requests.Enqueue(st);
416 {
417 queueEvent.Set();
418 requests.Enqueue(st);
419 }
420 421
421 MapBlockRequestData req = new MapBlockRequestData(); 422 MapBlockRequestData req = new MapBlockRequestData();
422 423
@@ -599,55 +600,106 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
599 public void process() 600 public void process()
600 { 601 {
601 const int MAX_ASYNC_REQUESTS = 20; 602 const int MAX_ASYNC_REQUESTS = 20;
603 ScenePresence av = null;
604 MapRequestState st = null;
605
602 try 606 try
603 { 607 {
604 while (true) 608 while (true)
605 { 609 {
606 MapRequestState st = new MapRequestState(); 610 Watchdog.UpdateThread();
607 bool valid = false; 611
608 queueEvent.WaitOne(); 612 av = null;
609 lock (requests) 613 st = null;
610 { 614
611 if (requests.Count > 0) 615 st = requests.Dequeue(4900); // timeout to make watchdog happy
612 { 616
613 st = requests.Dequeue(); 617 if (st == null || st.agentID == UUID.Zero)
614 valid = true;
615 }
616 if (requests.Count == 0)
617 queueEvent.Reset();
618 }
619 if (!valid)
620 continue; 618 continue;
621 619
622 // end gracefully 620 // end gracefully
623 if (st.agentID == STOP_UUID) 621 if (st.agentID == STOP_UUID)
624 break; 622 break;
625 623
626 if (st.agentID != UUID.Zero) 624 // agent gone?
625
626 m_scene.TryGetScenePresence(st.agentID, out av);
627 if (av == null || av.IsChildAgent || av.IsDeleted || av.IsInTransit)
628 continue;
629
630 // region unreachable?
631 if (m_blacklistedregions.Contains(st.regionhandle))
632 continue;
633
634 bool dorequest = true;
635 OSDMap responseMap = null;
636
637 // check if we are already serving this region
638 lock (m_cachedRegionMapItemsResponses)
627 { 639 {
628 bool dorequest = true; 640 if (m_cachedRegionMapItemsResponses.Contains(st.regionhandle))
629 lock (m_rootAgents)
630 { 641 {
631 if (!m_rootAgents.Contains(st.agentID)) 642 m_cachedRegionMapItemsResponses.TryGetValue(st.regionhandle, out responseMap);
632 dorequest = false; 643 dorequest = false;
633 } 644 }
645 else
646 m_cachedRegionMapItemsResponses.Add(st.regionhandle, null, expireResponsesTime); // a bit more time for the access
647 }
634 648
635 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 649 if (dorequest)
650 {
651 // nothig for region, fire a request
652 Interlocked.Increment(ref nAsyncRequests);
653 MapRequestState rst = st;
654 Util.FireAndForget(x =>
636 { 655 {
637 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 656 RequestMapItemsAsync(rst.agentID, rst.flags, rst.EstateID, rst.godlike, rst.itemtype, rst.regionhandle);
638 Thread.Sleep(100); 657 });
639 658 }
640 Interlocked.Increment(ref nAsyncRequests); 659 else
641 Util.FireAndForget(x => 660 {
661 // do we have the response?
662 if (responseMap != null)
663 {
664 if(av!=null)
642 { 665 {
643 RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); 666 if (responseMap.ContainsKey(st.itemtype.ToString()))
644 }); 667 {
668 List<mapItemReply> returnitems = new List<mapItemReply>();
669 OSDArray itemarray = (OSDArray)responseMap[st.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(), st.itemtype, st.flags & 0xffff);
683 }
684 }
685 }
686 else
687 {
688 // request still beeing processed, enqueue it back
689 requests.Enqueue(st);
690 if (requests.Count() < 3)
691 Thread.Sleep(100);
645 } 692 }
646 } 693 }
647 694
648 Watchdog.UpdateThread(); 695 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
696 {
697 Thread.Sleep(100);
698 Watchdog.UpdateThread();
699 }
649 } 700 }
650 } 701 }
702
651 catch (Exception e) 703 catch (Exception e)
652 { 704 {
653 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e); 705 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
@@ -658,20 +710,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
658 } 710 }
659 711
660 /// <summary> 712 /// <summary>
661 /// Enqueues the map item request into the processing thread
662 /// </summary>
663 /// <param name="state"></param>
664 public void EnqueueMapItemRequest(MapRequestState state)
665 {
666 lock (requests)
667 {
668 queueEvent.Set();
669 requests.Enqueue(state);
670
671 }
672 }
673
674 /// <summary>
675 /// Enqueue the MapItem request for remote processing 713 /// Enqueue the MapItem request for remote processing
676 /// </summary> 714 /// </summary>
677 /// <param name="httpserver">blank string, we discover this in the process</param> 715 /// <param name="httpserver">blank string, we discover this in the process</param>
@@ -691,7 +729,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
691 st.godlike = godlike; 729 st.godlike = godlike;
692 st.itemtype = itemtype; 730 st.itemtype = itemtype;
693 st.regionhandle = regionhandle; 731 st.regionhandle = regionhandle;
694 EnqueueMapItemRequest(st); 732
733 requests.Enqueue(st);
695 } 734 }
696 735
697 /// <summary> 736 /// <summary>
@@ -711,24 +750,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
711 private void RequestMapItemsAsync(UUID id, uint flags, 750 private void RequestMapItemsAsync(UUID id, uint flags,
712 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 751 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
713 { 752 {
714 // m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 753 // m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
715 754
716 string httpserver = ""; 755 string httpserver = "";
717 bool blacklisted = false; 756 bool blacklisted = false;
718 lock (m_blacklistedregions)
719 {
720 if (m_blacklistedregions.ContainsKey(regionhandle))
721 {
722 if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout))
723 {
724 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle);
725 757
726 m_blacklistedregions.Remove(regionhandle); 758 lock (m_blacklistedregions)
727 } 759 blacklisted = m_blacklistedregions.Contains(regionhandle);
728 else
729 blacklisted = true;
730 }
731 }
732 760
733 if (blacklisted) 761 if (blacklisted)
734 { 762 {
@@ -738,60 +766,36 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
738 766
739 UUID requestID = UUID.Random(); 767 UUID requestID = UUID.Random();
740 lock (m_cachedRegionMapItemsAddress) 768 lock (m_cachedRegionMapItemsAddress)
741 { 769 m_cachedRegionMapItemsAddress.TryGetValue(regionhandle, out httpserver);
742 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
743 httpserver = m_cachedRegionMapItemsAddress[regionhandle];
744 }
745 770
746 if (httpserver.Length == 0) 771 if (httpserver == null || httpserver.Length == 0)
747 { 772 {
748 uint x = 0, y = 0; 773 uint x = 0, y = 0;
749 Util.RegionHandleToWorldLoc(regionhandle, out x, out y); 774 Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
775
750 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 776 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
751 777
752 if (mreg != null) 778 if (mreg != null)
753 { 779 {
754 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); 780 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString();
755 lock (m_cachedRegionMapItemsAddress) 781 lock (m_cachedRegionMapItemsAddress)
756 { 782 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle, httpserver, 2.0 * expireBlackListTime);
757 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
758 m_cachedRegionMapItemsAddress.Add(regionhandle, httpserver);
759 }
760 }
761 else
762 {
763 lock (m_blacklistedregions)
764 {
765 if (!m_blacklistedregions.ContainsKey(regionhandle))
766 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
767 }
768 //m_log.InfoFormat("[WORLD MAP]: Blacklisted region {0}", regionhandle.ToString());
769 } 783 }
770 } 784 }
771 785
772 blacklisted = false;
773 lock (m_blacklistedurls) 786 lock (m_blacklistedurls)
774 { 787 {
775 if (m_blacklistedurls.ContainsKey(httpserver)) 788 if (httpserver == null || httpserver.Length == 0 || m_blacklistedurls.Contains(httpserver))
776 { 789 {
777 if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) 790 // Can't find the http server or its blocked
778 { 791 lock (m_blacklistedregions)
779 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver); 792 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
780 793
781 m_blacklistedurls.Remove(httpserver); 794 Interlocked.Decrement(ref nAsyncRequests);
782 } 795 return;
783 else
784 blacklisted = true;
785 } 796 }
786 } 797 }
787 798
788 // Can't find the http server
789 if (httpserver.Length == 0 || blacklisted)
790 {
791 Interlocked.Decrement(ref nAsyncRequests);
792 return;
793 }
794
795 WebRequest mapitemsrequest = null; 799 WebRequest mapitemsrequest = null;
796 try 800 try
797 { 801 {
@@ -806,34 +810,30 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
806 810
807 mapitemsrequest.Method = "POST"; 811 mapitemsrequest.Method = "POST";
808 mapitemsrequest.ContentType = "application/xml+llsd"; 812 mapitemsrequest.ContentType = "application/xml+llsd";
809 OSDMap RAMap = new OSDMap();
810 813
814 OSDMap RAMap = new OSDMap();
811 // string RAMapString = RAMap.ToString(); 815 // string RAMapString = RAMap.ToString();
812 OSD LLSDofRAMap = RAMap; // RENAME if this works 816 OSD LLSDofRAMap = RAMap; // RENAME if this works
813 817
814 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); 818 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
819
815 OSDMap responseMap = new OSDMap(); 820 OSDMap responseMap = new OSDMap();
816 responseMap["requestID"] = OSD.FromUUID(requestID);
817 821
818 Stream os = null;
819 try 822 try
820 { // send the Post 823 { // send the Post
821 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send 824 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send
822 os = mapitemsrequest.GetRequestStream(); 825 using (Stream os = mapitemsrequest.GetRequestStream())
823 os.Write(buffer, 0, buffer.Length); //Send it 826 os.Write(buffer, 0, buffer.Length); //Send it
824 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver); 827 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver);
825 } 828 }
826 catch (WebException ex) 829 catch (WebException ex)
827 { 830 {
828 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 831 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
829 responseMap["connect"] = OSD.FromBoolean(false); 832 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
830 lock (m_blacklistedurls) 833 lock (m_blacklistedurls)
831 { 834 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
832 if (!m_blacklistedurls.ContainsKey(httpserver)) 835 lock (m_blacklistedregions)
833 m_blacklistedurls.Add(httpserver, Environment.TickCount); 836 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
834 }
835
836 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
837 837
838 Interlocked.Decrement(ref nAsyncRequests); 838 Interlocked.Decrement(ref nAsyncRequests);
839 return; 839 return;
@@ -844,11 +844,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
844 Interlocked.Decrement(ref nAsyncRequests); 844 Interlocked.Decrement(ref nAsyncRequests);
845 return; 845 return;
846 } 846 }
847 finally
848 {
849 if (os != null)
850 os.Dispose();
851 }
852 847
853 string response_mapItems_reply = null; 848 string response_mapItems_reply = null;
854 { // get the response 849 { // get the response
@@ -873,12 +868,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
873 catch (WebException) 868 catch (WebException)
874 { 869 {
875 lock (m_blacklistedurls) 870 lock (m_blacklistedurls)
876 { 871 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
877 if (!m_blacklistedurls.ContainsKey(httpserver)) 872 lock (m_blacklistedregions)
878 m_blacklistedurls.Add(httpserver, Environment.TickCount); 873 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
879 }
880 874
881 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 875 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
882 876
883 Interlocked.Decrement(ref nAsyncRequests); 877 Interlocked.Decrement(ref nAsyncRequests);
884 return; 878 return;
@@ -887,46 +881,39 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
887 { 881 {
888 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 882 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
889 lock (m_blacklistedregions) 883 lock (m_blacklistedregions)
890 { 884 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
891 if (!m_blacklistedregions.ContainsKey(regionhandle))
892 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
893 }
894 885
895 Interlocked.Decrement(ref nAsyncRequests); 886 Interlocked.Decrement(ref nAsyncRequests);
896 return; 887 return;
897 } 888 }
898 889
899 OSD rezResponse = null;
900 try 890 try
901 { 891 {
902 rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply); 892 responseMap = (OSDMap)OSDParser.DeserializeLLSDXml(response_mapItems_reply);
903
904 responseMap = (OSDMap)rezResponse;
905 responseMap["requestID"] = OSD.FromUUID(requestID);
906 } 893 }
907 catch (Exception ex) 894 catch (Exception ex)
908 { 895 {
909 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 896 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
910 lock (m_blacklistedregions) 897 lock (m_blacklistedregions)
911 { 898 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
912 if (!m_blacklistedregions.ContainsKey(regionhandle))
913 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
914 }
915 899
916 Interlocked.Decrement(ref nAsyncRequests); 900 Interlocked.Decrement(ref nAsyncRequests);
917 return; 901 return;
918 } 902 }
919 } 903 }
920 904
921 Interlocked.Decrement(ref nAsyncRequests); 905 // cache the response that may include other valid items
906 lock (m_cachedRegionMapItemsResponses)
907 m_cachedRegionMapItemsResponses.AddOrUpdate(regionhandle, responseMap, expireResponsesTime);
922 908
909 // send answer for this item and client
923 flags &= 0xffff; 910 flags &= 0xffff;
924 911
925 if (id != UUID.Zero) 912 if (id != UUID.Zero)
926 { 913 {
927 ScenePresence av = null; 914 ScenePresence av = null;
928 m_scene.TryGetScenePresence(id, out av); 915 m_scene.TryGetScenePresence(id, out av);
929 if (av != null) 916 if (av != null && !av.IsChildAgent && !av.IsDeleted && !av.IsInTransit)
930 { 917 {
931 if (responseMap.ContainsKey(itemtype.ToString())) 918 if (responseMap.ContainsKey(itemtype.ToString()))
932 { 919 {
@@ -946,54 +933,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
946 } 933 }
947 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags); 934 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
948 } 935 }
949
950 /* send things viewer didn't ask ?
951 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
952 itemtype = 7;
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 // Service 1 (MAP_ITEM_TELEHUB)
974 itemtype = 1;
975
976 if (responseMap.ContainsKey(itemtype.ToString()))
977 {
978 List<mapItemReply> returnitems = new List<mapItemReply>();
979 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
980 for (int i = 0; i < itemarray.Count; i++)
981 {
982 OSDMap mapitem = (OSDMap)itemarray[i];
983 mapItemReply mi = new mapItemReply();
984 mi.x = (uint)mapitem["X"].AsInteger();
985 mi.y = (uint)mapitem["Y"].AsInteger();
986 mi.id = mapitem["ID"].AsUUID();
987 mi.Extra = mapitem["Extra"].AsInteger();
988 mi.Extra2 = mapitem["Extra2"].AsInteger();
989 mi.name = mapitem["Name"].AsString();
990 returnitems.Add(mi);
991 }
992 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
993 }
994 */
995 } 936 }
996 } 937 }
938
939 Interlocked.Decrement(ref nAsyncRequests);
997 } 940 }
998 941
999 /// <summary> 942 /// <summary>
@@ -1160,67 +1103,71 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1160 1103
1161 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1104 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1162 { 1105 {
1163 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1164 Hashtable reply = new Hashtable(); 1106 Hashtable reply = new Hashtable();
1165 int statuscode = 200; 1107 int statuscode = 200;
1166 byte[] jpeg = new byte[0]; 1108 byte[] jpeg = new byte[0];
1167 1109
1168 if (myMapImageJPEG.Length == 0) 1110 if (m_scene.RegionInfo.RegionSettings.TerrainImageID != UUID.Zero)
1169 { 1111 {
1170 MemoryStream imgstream = null; 1112 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1171 Bitmap mapTexture = new Bitmap(1, 1);
1172 ManagedImage managedImage;
1173 Image image = (Image)mapTexture;
1174 1113
1175 try 1114 if (myMapImageJPEG.Length == 0)
1176 { 1115 {
1177 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data 1116 MemoryStream imgstream = null;
1117 Bitmap mapTexture = new Bitmap(1, 1);
1118 ManagedImage managedImage;
1119 Image image = (Image)mapTexture;
1178 1120
1179 imgstream = new MemoryStream(); 1121 try
1122 {
1123 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data
1180 1124
1181 // non-async because we know we have the asset immediately. 1125 imgstream = new MemoryStream();
1182 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
1183 1126
1184 // Decode image to System.Drawing.Image 1127 // non-async because we know we have the asset immediately.
1185 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image)) 1128 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
1186 {
1187 // Save to bitmap
1188 mapTexture = new Bitmap(image);
1189 1129
1190 EncoderParameters myEncoderParameters = new EncoderParameters(); 1130 // Decode image to System.Drawing.Image
1191 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); 1131 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image))
1132 {
1133 // Save to bitmap
1134 mapTexture = new Bitmap(image);
1135
1136 EncoderParameters myEncoderParameters = new EncoderParameters();
1137 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
1192 1138
1193 // Save bitmap to stream 1139 // Save bitmap to stream
1194 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters); 1140 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters);
1195 1141
1196 // Write the stream to a byte array for output 1142 // Write the stream to a byte array for output
1197 jpeg = imgstream.ToArray(); 1143 jpeg = imgstream.ToArray();
1198 myMapImageJPEG = jpeg; 1144 myMapImageJPEG = jpeg;
1145 }
1199 } 1146 }
1200 } 1147 catch (Exception)
1201 catch (Exception) 1148 {
1202 { 1149 // Dummy!
1203 // Dummy! 1150 m_log.Warn("[WORLD MAP]: Unable to generate Map image");
1204 m_log.Warn("[WORLD MAP]: Unable to generate Map image"); 1151 }
1205 } 1152 finally
1206 finally 1153 {
1207 { 1154 // Reclaim memory, these are unmanaged resources
1208 // Reclaim memory, these are unmanaged resources 1155 // If we encountered an exception, one or more of these will be null
1209 // If we encountered an exception, one or more of these will be null 1156 if (mapTexture != null)
1210 if (mapTexture != null) 1157 mapTexture.Dispose();
1211 mapTexture.Dispose();
1212 1158
1213 if (image != null) 1159 if (image != null)
1214 image.Dispose(); 1160 image.Dispose();
1215 1161
1216 if (imgstream != null) 1162 if (imgstream != null)
1217 imgstream.Dispose(); 1163 imgstream.Dispose();
1164 }
1165 }
1166 else
1167 {
1168 // Use cached version so we don't have to loose our mind
1169 jpeg = myMapImageJPEG;
1218 } 1170 }
1219 }
1220 else
1221 {
1222 // Use cached version so we don't have to loose our mind
1223 jpeg = myMapImageJPEG;
1224 } 1171 }
1225 1172
1226 reply["str_response_string"] = Convert.ToBase64String(jpeg); 1173 reply["str_response_string"] = Convert.ToBase64String(jpeg);
@@ -1290,15 +1237,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1290 { 1237 {
1291 textures.Add(texAsset); 1238 textures.Add(texAsset);
1292 } 1239 }
1293 //else
1294 //{
1295 // // WHAT?!? This doesn't seem right. Commenting (diva)
1296 // texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
1297 // if (texAsset != null)
1298 // {
1299 // textures.Add(texAsset);
1300 // }
1301 //}
1302 } 1240 }
1303 1241
1304 foreach (AssetBase asset in textures) 1242 foreach (AssetBase asset in textures)
@@ -1338,26 +1276,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1338 1276
1339 GenerateMaptile(); 1277 GenerateMaptile();
1340 } 1278 }
1341 /*
1342 if (m_mapImageGenerator == null)
1343 {
1344 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1345 return;
1346 }
1347 1279
1348 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
1349 {
1350 GenerateMaptile(mapbmp);
1351 if(m_mapImageServiceModule != null)
1352 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1353 }
1354 }
1355 */
1356 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) 1280 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
1357 { 1281 {
1358 uint xstart = 0; 1282 uint xstart = 0;
1359 uint ystart = 0; 1283 uint ystart = 0;
1360 1284
1285 // create and send back answers about all items active
1286 // so call region can cache them and answer to the several
1287 // individual item viewer requests
1288
1361 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); 1289 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
1362 1290
1363 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots) 1291 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots)
@@ -1605,20 +1533,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1605 1533
1606 lock (m_blacklistedregions) 1534 lock (m_blacklistedregions)
1607 { 1535 {
1608 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1536 if (m_blacklistedregions.Contains(regionhandle))
1609 m_blacklistedregions.Remove(regionhandle); 1537 m_blacklistedregions.Remove(regionhandle);
1610 } 1538 }
1611 1539
1612 lock (m_blacklistedurls) 1540 lock (m_blacklistedurls)
1613 { 1541 {
1614 if (m_blacklistedurls.ContainsKey(httpserver)) 1542 if (m_blacklistedurls.Contains(httpserver))
1615 m_blacklistedurls.Remove(httpserver); 1543 m_blacklistedurls.Remove(httpserver);
1616 } 1544 }
1617 1545
1618 lock (m_cachedRegionMapItemsAddress) 1546 lock (m_cachedRegionMapItemsAddress)
1619 { 1547 {
1620 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 1548 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle,
1621 m_cachedRegionMapItemsAddress.Remove(regionhandle); 1549 httpserver, 5.0 * expireBlackListTime);
1622 } 1550 }
1623 } 1551 }
1624 1552
@@ -1706,7 +1634,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1706 } 1634 }
1707 } 1635 }
1708 1636
1709 public struct MapRequestState 1637 public class MapRequestState
1710 { 1638 {
1711 public UUID agentID; 1639 public UUID agentID;
1712 public uint flags; 1640 public uint flags;