diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/World')
-rw-r--r-- | OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs | 9 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | 456 |
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; |