aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorMelanie2012-07-08 06:06:33 +0200
committerMelanie2012-07-08 06:06:33 +0200
commitd3b778ebbe617a37a32c866101c75284dad8f15a (patch)
tree9e1b8dfdd6ae21607fead5149486494a5ec84374 /OpenSim
parentChange semantics of FromXML on vehicle data to make the serializer a bit cleaner (diff)
downloadopensim-SC-d3b778ebbe617a37a32c866101c75284dad8f15a.zip
opensim-SC-d3b778ebbe617a37a32c866101c75284dad8f15a.tar.gz
opensim-SC-d3b778ebbe617a37a32c866101c75284dad8f15a.tar.bz2
opensim-SC-d3b778ebbe617a37a32c866101c75284dad8f15a.tar.xz
Address map lag issue seen with non-avination viewers
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs161
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs357
-rw-r--r--OpenSim/Server/Handlers/Map/MapGetServerConnector.cs15
3 files changed, 271 insertions, 262 deletions
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index 4e6bfb8..2417b1a 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -86,90 +86,93 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
86 86
87 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 87 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
88 { 88 {
89 if (mapName.Length < 2) 89 Util.FireAndForget(x =>
90 { 90 {
91 remoteClient.SendAlertMessage("Use a search string with at least 2 characters"); 91 if (mapName.Length < 2)
92 return; 92 {
93 } 93 remoteClient.SendAlertMessage("Use a search string with at least 2 characters");
94 return;
95 }
94 96
95 //m_log.DebugFormat("MAP NAME=({0})", mapName); 97 //m_log.DebugFormat("MAP NAME=({0})", mapName);
96 98
97 // Hack to get around the fact that ll V3 now drops the port from the 99 // Hack to get around the fact that ll V3 now drops the port from the
98 // map name. See https://jira.secondlife.com/browse/VWR-28570 100 // map name. See https://jira.secondlife.com/browse/VWR-28570
99 // 101 //
100 // Caller, use this magic form instead: 102 // Caller, use this magic form instead:
101 // secondlife://http|!!mygrid.com|8002|Region+Name/128/128 103 // secondlife://http|!!mygrid.com|8002|Region+Name/128/128
102 // or url encode if possible. 104 // or url encode if possible.
103 // the hacks we do with this viewer... 105 // the hacks we do with this viewer...
104 // 106 //
105 string mapNameOrig = mapName; 107 string mapNameOrig = mapName;
106 if (mapName.Contains("|")) 108 if (mapName.Contains("|"))
107 mapName = mapName.Replace('|', ':'); 109 mapName = mapName.Replace('|', ':');
108 if (mapName.Contains("+")) 110 if (mapName.Contains("+"))
109 mapName = mapName.Replace('+', ' '); 111 mapName = mapName.Replace('+', ' ');
110 if (mapName.Contains("!")) 112 if (mapName.Contains("!"))
111 mapName = mapName.Replace('!', '/'); 113 mapName = mapName.Replace('!', '/');
112 114
113 // try to fetch from GridServer 115 // try to fetch from GridServer
114 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); 116 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
115// if (regionInfos.Count == 0) 117 // if (regionInfos.Count == 0)
116// remoteClient.SendAlertMessage("Hyperlink could not be established."); 118 // remoteClient.SendAlertMessage("Hyperlink could not be established.");
117 119
118 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count); 120 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
119 List<MapBlockData> blocks = new List<MapBlockData>(); 121 List<MapBlockData> blocks = new List<MapBlockData>();
120 122
121 MapBlockData data; 123 MapBlockData data;
122 if (regionInfos.Count > 0) 124 if (regionInfos.Count > 0)
123 {
124 foreach (GridRegion info in regionInfos)
125 { 125 {
126 data = new MapBlockData(); 126 foreach (GridRegion info in regionInfos)
127 data.Agents = 0; 127 {
128 data.Access = info.Access; 128 data = new MapBlockData();
129 if (flags == 2) // V2 sends this 129 data.Agents = 0;
130 data.MapImageId = UUID.Zero; 130 data.Access = info.Access;
131 else 131 if (flags == 2) // V2 sends this
132 data.MapImageId = info.TerrainImage; 132 data.MapImageId = UUID.Zero;
133 // ugh! V2-3 is very sensitive about the result being 133 else
134 // exactly the same as the requested name 134 data.MapImageId = info.TerrainImage;
135 if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+")) 135 // ugh! V2-3 is very sensitive about the result being
136 data.Name = mapNameOrig; 136 // exactly the same as the requested name
137 else 137 if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+"))
138 data.Name = info.RegionName; 138 data.Name = mapNameOrig;
139 data.RegionFlags = 0; // TODO not used? 139 else
140 data.WaterHeight = 0; // not used 140 data.Name = info.RegionName;
141 data.X = (ushort)(info.RegionLocX / Constants.RegionSize); 141 data.RegionFlags = 0; // TODO not used?
142 data.Y = (ushort)(info.RegionLocY / Constants.RegionSize); 142 data.WaterHeight = 0; // not used
143 blocks.Add(data); 143 data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
144 data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
145 blocks.Add(data);
146 }
144 } 147 }
145 }
146 148
147 // final block, closing the search result 149 // final block, closing the search result
148 data = new MapBlockData(); 150 data = new MapBlockData();
149 data.Agents = 0; 151 data.Agents = 0;
150 data.Access = 255; 152 data.Access = 255;
151 data.MapImageId = UUID.Zero; 153 data.MapImageId = UUID.Zero;
152 data.Name = mapName; 154 data.Name = mapName;
153 data.RegionFlags = 0; 155 data.RegionFlags = 0;
154 data.WaterHeight = 0; // not used 156 data.WaterHeight = 0; // not used
155 data.X = 0; 157 data.X = 0;
156 data.Y = 0; 158 data.Y = 0;
157 blocks.Add(data); 159 blocks.Add(data);
158 160
159 // flags are agent flags sent from the viewer. 161 // flags are agent flags sent from the viewer.
160 // they have different values depending on different viewers, apparently 162 // they have different values depending on different viewers, apparently
161 remoteClient.SendMapBlock(blocks, flags); 163 remoteClient.SendMapBlock(blocks, flags);
162 164
163 // send extra user messages for V3 165 // send extra user messages for V3
164 // because the UI is very confusing 166 // because the UI is very confusing
165 // while we don't fix the hard-coded urls 167 // while we don't fix the hard-coded urls
166 if (flags == 2) 168 if (flags == 2)
167 { 169 {
168 if (regionInfos.Count == 0) 170 if (regionInfos.Count == 0)
169 remoteClient.SendAgentAlertMessage("No regions found with that name.", true); 171 remoteClient.SendAgentAlertMessage("No regions found with that name.", true);
170 else if (regionInfos.Count == 1) 172 else if (regionInfos.Count == 1)
171 remoteClient.SendAgentAlertMessage("Region found!", false); 173 remoteClient.SendAgentAlertMessage("Region found!", false);
172 } 174 }
175 });
173 } 176 }
174 177
175// private Scene GetClientScene(IClientAPI client) 178// private Scene GetClientScene(IClientAPI client)
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 899e5ea..721ac5c 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -63,7 +63,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
63 private static readonly UUID STOP_UUID = UUID.Random(); 63 private static readonly UUID STOP_UUID = UUID.Random();
64 private static readonly string m_mapLayerPath = "0001/"; 64 private static readonly string m_mapLayerPath = "0001/";
65 65
66 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>(); 66 private ManualResetEvent queueEvent = new ManualResetEvent(false);
67 private Queue<MapRequestState> requests = new Queue<MapRequestState>();
67 68
68 protected Scene m_scene; 69 protected Scene m_scene;
69 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 70 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
@@ -71,7 +72,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
71 private int blacklistTimeout = 10*60*1000; // 10 minutes 72 private int blacklistTimeout = 10*60*1000; // 10 minutes
72 private byte[] myMapImageJPEG; 73 private byte[] myMapImageJPEG;
73 protected volatile bool m_Enabled = false; 74 protected volatile bool m_Enabled = false;
74 private Dictionary<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>();
75 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); 75 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>();
76 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 76 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>();
77 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 77 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>();
@@ -368,7 +368,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
368 st.itemtype=0; 368 st.itemtype=0;
369 st.regionhandle=0; 369 st.regionhandle=0;
370 370
371 requests.Enqueue(st); 371 lock (requests)
372 {
373 queueEvent.Set();
374 requests.Enqueue(st);
375 }
372 } 376 }
373 377
374 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 378 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -519,12 +523,26 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
519 /// </summary> 523 /// </summary>
520 public void process() 524 public void process()
521 { 525 {
522 const int MAX_ASYNC_REQUESTS = 20; 526 const int MAX_ASYNC_REQUESTS = 5;
523 try 527 try
524 { 528 {
525 while (true) 529 while (true)
526 { 530 {
527 MapRequestState st = requests.Dequeue(1000); 531 MapRequestState st = new MapRequestState();
532 bool valid = false;
533 queueEvent.WaitOne();
534 lock (requests)
535 {
536 if (requests.Count > 0)
537 {
538 st = requests.Dequeue();
539 valid = true;
540 }
541 if (requests.Count == 0)
542 queueEvent.Reset();
543 }
544 if (!valid)
545 continue;
528 546
529 // end gracefully 547 // end gracefully
530 if (st.agentID == STOP_UUID) 548 if (st.agentID == STOP_UUID)
@@ -541,14 +559,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
541 559
542 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 560 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
543 { 561 {
544 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 562// while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
545 Thread.Sleep(80); 563// Thread.Sleep(500);
546 564
547 RequestMapItemsDelegate d = RequestMapItemsAsync;
548 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
549 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
550 //RequestMapItemsCompleted(response);
551 Interlocked.Increment(ref nAsyncRequests); 565 Interlocked.Increment(ref nAsyncRequests);
566 RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
552 } 567 }
553 } 568 }
554 569
@@ -570,110 +585,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
570 /// <param name="state"></param> 585 /// <param name="state"></param>
571 public void EnqueueMapItemRequest(MapRequestState state) 586 public void EnqueueMapItemRequest(MapRequestState state)
572 { 587 {
573 requests.Enqueue(state); 588 lock (requests)
574 }
575
576 /// <summary>
577 /// Sends the mapitem response to the IClientAPI
578 /// </summary>
579 /// <param name="response">The OSDMap Response for the mapitem</param>
580 private void RequestMapItemsCompleted(IAsyncResult iar)
581 {
582 AsyncResult result = (AsyncResult)iar;
583 RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate;
584
585 OSDMap response = (OSDMap)icon.EndInvoke(iar);
586
587 Interlocked.Decrement(ref nAsyncRequests);
588
589 if (!response.ContainsKey("requestID"))
590 return;
591
592 UUID requestID = response["requestID"].AsUUID();
593
594 if (requestID != UUID.Zero)
595 { 589 {
596 MapRequestState mrs = new MapRequestState(); 590 queueEvent.Set();
597 mrs.agentID = UUID.Zero; 591 requests.Enqueue(state);
598 lock (m_openRequests)
599 {
600 if (m_openRequests.ContainsKey(requestID))
601 {
602 mrs = m_openRequests[requestID];
603 m_openRequests.Remove(requestID);
604 }
605 }
606
607 if (mrs.agentID != UUID.Zero)
608 {
609 ScenePresence av = null;
610 m_scene.TryGetScenePresence(mrs.agentID, out av);
611 if (av != null)
612 {
613 if (response.ContainsKey(mrs.itemtype.ToString()))
614 {
615 List<mapItemReply> returnitems = new List<mapItemReply>();
616 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()];
617 for (int i = 0; i < itemarray.Count; i++)
618 {
619 OSDMap mapitem = (OSDMap)itemarray[i];
620 mapItemReply mi = new mapItemReply();
621 mi.x = (uint)mapitem["X"].AsInteger();
622 mi.y = (uint)mapitem["Y"].AsInteger();
623 mi.id = mapitem["ID"].AsUUID();
624 mi.Extra = mapitem["Extra"].AsInteger();
625 mi.Extra2 = mapitem["Extra2"].AsInteger();
626 mi.name = mapitem["Name"].AsString();
627 returnitems.Add(mi);
628 }
629 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
630 }
631
632 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
633 uint itemtype = 7;
634
635 if (response.ContainsKey(itemtype.ToString()))
636 {
637 List<mapItemReply> returnitems = new List<mapItemReply>();
638 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
639 for (int i = 0; i < itemarray.Count; i++)
640 {
641 OSDMap mapitem = (OSDMap)itemarray[i];
642 mapItemReply mi = new mapItemReply();
643 mi.x = (uint)mapitem["X"].AsInteger();
644 mi.y = (uint)mapitem["Y"].AsInteger();
645 mi.id = mapitem["ID"].AsUUID();
646 mi.Extra = mapitem["Extra"].AsInteger();
647 mi.Extra2 = mapitem["Extra2"].AsInteger();
648 mi.name = mapitem["Name"].AsString();
649 returnitems.Add(mi);
650 }
651 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
652 }
653
654 // Service 1 (MAP_ITEM_TELEHUB)
655 itemtype = 1;
656
657 if (response.ContainsKey(itemtype.ToString()))
658 {
659 List<mapItemReply> returnitems = new List<mapItemReply>();
660 OSDArray itemarray = (OSDArray)response[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(), itemtype, mrs.flags);
674 }
675 }
676 }
677 } 592 }
678 } 593 }
679 594
@@ -700,8 +615,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
700 EnqueueMapItemRequest(st); 615 EnqueueMapItemRequest(st);
701 } 616 }
702 617
703 private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags,
704 uint EstateID, bool godlike, uint itemtype, ulong regionhandle);
705 /// <summary> 618 /// <summary>
706 /// Does the actual remote mapitem request 619 /// Does the actual remote mapitem request
707 /// This should be called from an asynchronous thread 620 /// This should be called from an asynchronous thread
@@ -716,7 +629,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
716 /// <param name="itemtype">passed in from packet</param> 629 /// <param name="itemtype">passed in from packet</param>
717 /// <param name="regionhandle">Region we're looking up</param> 630 /// <param name="regionhandle">Region we're looking up</param>
718 /// <returns></returns> 631 /// <returns></returns>
719 private OSDMap RequestMapItemsAsync(UUID id, uint flags, 632 private void RequestMapItemsAsync(UUID id, uint flags,
720 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 633 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
721 { 634 {
722// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 635// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
@@ -739,7 +652,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
739 } 652 }
740 653
741 if (blacklisted) 654 if (blacklisted)
742 return new OSDMap(); 655 {
656 Interlocked.Decrement(ref nAsyncRequests);
657 return;
658 }
743 659
744 UUID requestID = UUID.Random(); 660 UUID requestID = UUID.Random();
745 lock (m_cachedRegionMapItemsAddress) 661 lock (m_cachedRegionMapItemsAddress)
@@ -747,6 +663,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
747 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 663 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
748 httpserver = m_cachedRegionMapItemsAddress[regionhandle]; 664 httpserver = m_cachedRegionMapItemsAddress[regionhandle];
749 } 665 }
666
750 if (httpserver.Length == 0) 667 if (httpserver.Length == 0)
751 { 668 {
752 uint x = 0, y = 0; 669 uint x = 0, y = 0;
@@ -791,18 +708,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
791 708
792 // Can't find the http server 709 // Can't find the http server
793 if (httpserver.Length == 0 || blacklisted) 710 if (httpserver.Length == 0 || blacklisted)
794 return new OSDMap(); 711 {
795 712 Interlocked.Decrement(ref nAsyncRequests);
796 MapRequestState mrs = new MapRequestState(); 713 return;
797 mrs.agentID = id; 714 }
798 mrs.EstateID = EstateID;
799 mrs.flags = flags;
800 mrs.godlike = godlike;
801 mrs.itemtype=itemtype;
802 mrs.regionhandle = regionhandle;
803
804 lock (m_openRequests)
805 m_openRequests.Add(requestID, mrs);
806 715
807 WebRequest mapitemsrequest = null; 716 WebRequest mapitemsrequest = null;
808 try 717 try
@@ -812,7 +721,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
812 catch (Exception e) 721 catch (Exception e)
813 { 722 {
814 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); 723 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
815 return new OSDMap(); 724 Interlocked.Decrement(ref nAsyncRequests);
725 return;
816 } 726 }
817 727
818 mapitemsrequest.Method = "POST"; 728 mapitemsrequest.Method = "POST";
@@ -826,6 +736,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
826 OSDMap responseMap = new OSDMap(); 736 OSDMap responseMap = new OSDMap();
827 responseMap["requestID"] = OSD.FromUUID(requestID); 737 responseMap["requestID"] = OSD.FromUUID(requestID);
828 738
739return;
829 Stream os = null; 740 Stream os = null;
830 try 741 try
831 { // send the Post 742 { // send the Post
@@ -837,7 +748,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
837 catch (WebException ex) 748 catch (WebException ex)
838 { 749 {
839 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 750 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
840 responseMap["connect"] = OSD.FromBoolean(false);
841 lock (m_blacklistedurls) 751 lock (m_blacklistedurls)
842 { 752 {
843 if (!m_blacklistedurls.ContainsKey(httpserver)) 753 if (!m_blacklistedurls.ContainsKey(httpserver))
@@ -846,13 +756,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
846 756
847 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 757 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
848 758
849 return responseMap; 759 Interlocked.Decrement(ref nAsyncRequests);
760 return;
850 } 761 }
851 catch 762 catch
852 { 763 {
853 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 764 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
854 responseMap["connect"] = OSD.FromBoolean(false); 765 Interlocked.Decrement(ref nAsyncRequests);
855 return responseMap; 766 return;
856 } 767 }
857 finally 768 finally
858 { 769 {
@@ -873,12 +784,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
873 } 784 }
874 else 785 else
875 { 786 {
876 return new OSDMap(); 787 Interlocked.Decrement(ref nAsyncRequests);
788 return;
877 } 789 }
878 } 790 }
879 catch (WebException) 791 catch (WebException)
880 { 792 {
881 responseMap["connect"] = OSD.FromBoolean(false);
882 lock (m_blacklistedurls) 793 lock (m_blacklistedurls)
883 { 794 {
884 if (!m_blacklistedurls.ContainsKey(httpserver)) 795 if (!m_blacklistedurls.ContainsKey(httpserver))
@@ -887,19 +798,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
887 798
888 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 799 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
889 800
890 return responseMap; 801 Interlocked.Decrement(ref nAsyncRequests);
802 return;
891 } 803 }
892 catch 804 catch
893 { 805 {
894 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 806 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
895 responseMap["connect"] = OSD.FromBoolean(false);
896 lock (m_blacklistedregions) 807 lock (m_blacklistedregions)
897 { 808 {
898 if (!m_blacklistedregions.ContainsKey(regionhandle)) 809 if (!m_blacklistedregions.ContainsKey(regionhandle))
899 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 810 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
900 } 811 }
901 812
902 return responseMap; 813 Interlocked.Decrement(ref nAsyncRequests);
814 return;
903 } 815 }
904 finally 816 finally
905 { 817 {
@@ -918,14 +830,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
918 catch (Exception ex) 830 catch (Exception ex)
919 { 831 {
920 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 832 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
921 responseMap["connect"] = OSD.FromBoolean(false);
922 lock (m_blacklistedregions) 833 lock (m_blacklistedregions)
923 { 834 {
924 if (!m_blacklistedregions.ContainsKey(regionhandle)) 835 if (!m_blacklistedregions.ContainsKey(regionhandle))
925 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 836 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
926 } 837 }
927 838
928 return responseMap; 839 Interlocked.Decrement(ref nAsyncRequests);
840 return;
929 } 841 }
930 } 842 }
931 843
@@ -939,7 +851,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
939 } 851 }
940 } 852 }
941 853
942 return responseMap; 854 Interlocked.Decrement(ref nAsyncRequests);
855
856 if (id != UUID.Zero)
857 {
858 ScenePresence av = null;
859 m_scene.TryGetScenePresence(id, out av);
860 if (av != null)
861 {
862 if (responseMap.ContainsKey(itemtype.ToString()))
863 {
864 List<mapItemReply> returnitems = new List<mapItemReply>();
865 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
866 for (int i = 0; i < itemarray.Count; i++)
867 {
868 OSDMap mapitem = (OSDMap)itemarray[i];
869 mapItemReply mi = new mapItemReply();
870 mi.x = (uint)mapitem["X"].AsInteger();
871 mi.y = (uint)mapitem["Y"].AsInteger();
872 mi.id = mapitem["ID"].AsUUID();
873 mi.Extra = mapitem["Extra"].AsInteger();
874 mi.Extra2 = mapitem["Extra2"].AsInteger();
875 mi.name = mapitem["Name"].AsString();
876 returnitems.Add(mi);
877 }
878 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
879 }
880
881 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
882 itemtype = 7;
883
884 if (responseMap.ContainsKey(itemtype.ToString()))
885 {
886 List<mapItemReply> returnitems = new List<mapItemReply>();
887 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
888 for (int i = 0; i < itemarray.Count; i++)
889 {
890 OSDMap mapitem = (OSDMap)itemarray[i];
891 mapItemReply mi = new mapItemReply();
892 mi.x = (uint)mapitem["X"].AsInteger();
893 mi.y = (uint)mapitem["Y"].AsInteger();
894 mi.id = mapitem["ID"].AsUUID();
895 mi.Extra = mapitem["Extra"].AsInteger();
896 mi.Extra2 = mapitem["Extra2"].AsInteger();
897 mi.name = mapitem["Name"].AsString();
898 returnitems.Add(mi);
899 }
900 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
901 }
902
903 // Service 1 (MAP_ITEM_TELEHUB)
904 itemtype = 1;
905
906 if (responseMap.ContainsKey(itemtype.ToString()))
907 {
908 List<mapItemReply> returnitems = new List<mapItemReply>();
909 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
910 for (int i = 0; i < itemarray.Count; i++)
911 {
912 OSDMap mapitem = (OSDMap)itemarray[i];
913 mapItemReply mi = new mapItemReply();
914 mi.x = (uint)mapitem["X"].AsInteger();
915 mi.y = (uint)mapitem["Y"].AsInteger();
916 mi.id = mapitem["ID"].AsUUID();
917 mi.Extra = mapitem["Extra"].AsInteger();
918 mi.Extra2 = mapitem["Extra2"].AsInteger();
919 mi.name = mapitem["Name"].AsString();
920 returnitems.Add(mi);
921 }
922 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
923 }
924 }
925 }
943 } 926 }
944 927
945 /// <summary> 928 /// <summary>
@@ -951,53 +934,56 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
951 /// <param name="maxY"></param> 934 /// <param name="maxY"></param>
952 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 935 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
953 { 936 {
954 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); 937 Util.FireAndForget(x =>
955 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible
956 { 938 {
957 List<MapBlockData> response = new List<MapBlockData>(); 939 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
958 940 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible
959 // this should return one mapblock at most. It is triggered by a click
960 // on an unloaded square.
961 // But make sure: Look whether the one we requested is in there
962 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
963 minX * (int)Constants.RegionSize,
964 maxX * (int)Constants.RegionSize,
965 minY * (int)Constants.RegionSize,
966 maxY * (int)Constants.RegionSize);
967
968 if (regions != null)
969 { 941 {
970 foreach (GridRegion r in regions) 942 List<MapBlockData> response = new List<MapBlockData>();
943
944 // this should return one mapblock at most. It is triggered by a click
945 // on an unloaded square.
946 // But make sure: Look whether the one we requested is in there
947 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
948 minX * (int)Constants.RegionSize,
949 maxX * (int)Constants.RegionSize,
950 minY * (int)Constants.RegionSize,
951 maxY * (int)Constants.RegionSize);
952
953 if (regions != null)
971 { 954 {
972 if ((r.RegionLocX == minX * (int)Constants.RegionSize) && 955 foreach (GridRegion r in regions)
973 (r.RegionLocY == minY * (int)Constants.RegionSize))
974 { 956 {
975 // found it => add it to response 957 if ((r.RegionLocX == minX * (int)Constants.RegionSize) &&
976 MapBlockData block = new MapBlockData(); 958 (r.RegionLocY == minY * (int)Constants.RegionSize))
977 MapBlockFromGridRegion(block, r, flag); 959 {
978 response.Add(block); 960 // found it => add it to response
979 break; 961 MapBlockData block = new MapBlockData();
962 MapBlockFromGridRegion(block, r, flag);
963 response.Add(block);
964 break;
965 }
980 } 966 }
981 } 967 }
982 }
983 968
984 if (response.Count == 0) 969 if (response.Count == 0)
970 {
971 // response still empty => couldn't find the map-tile the user clicked on => tell the client
972 MapBlockData block = new MapBlockData();
973 block.X = (ushort)minX;
974 block.Y = (ushort)minY;
975 block.Access = 254; // means 'simulator is offline'
976 response.Add(block);
977 }
978 // The lower 16 bits are an unsigned int16
979 remoteClient.SendMapBlock(response, flag & 0xffff);
980 }
981 else
985 { 982 {
986 // response still empty => couldn't find the map-tile the user clicked on => tell the client 983 // normal mapblock request. Use the provided values
987 MapBlockData block = new MapBlockData(); 984 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
988 block.X = (ushort)minX;
989 block.Y = (ushort)minY;
990 block.Access = 254; // means 'simulator is offline'
991 response.Add(block);
992 } 985 }
993 // The lower 16 bits are an unsigned int16 986 });
994 remoteClient.SendMapBlock(response, flag & 0xffff);
995 }
996 else
997 {
998 // normal mapblock request. Use the provided values
999 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
1000 }
1001 } 987 }
1002 988
1003 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 989 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
@@ -1013,8 +999,15 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1013 MapBlockData block = new MapBlockData(); 999 MapBlockData block = new MapBlockData();
1014 MapBlockFromGridRegion(block, r, flag); 1000 MapBlockFromGridRegion(block, r, flag);
1015 mapBlocks.Add(block); 1001 mapBlocks.Add(block);
1002 if (mapBlocks.Count >= 20)
1003 {
1004 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1005 mapBlocks.Clear();
1006 Thread.Sleep(1000);
1007 }
1016 } 1008 }
1017 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1009 if (mapBlocks.Count > 0)
1010 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1018 1011
1019 return mapBlocks; 1012 return mapBlocks;
1020 } 1013 }
diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
index fb85d1c..4502b7d 100644
--- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
+++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
@@ -29,6 +29,7 @@ using System;
29using System.IO; 29using System.IO;
30using System.Net; 30using System.Net;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32 33
33using Nini.Config; 34using Nini.Config;
34using log4net; 35using log4net;
@@ -70,6 +71,8 @@ namespace OpenSim.Server.Handlers.MapImage
70 71
71 class MapServerGetHandler : BaseStreamHandler 72 class MapServerGetHandler : BaseStreamHandler
72 { 73 {
74 public static ManualResetEvent ev = new ManualResetEvent(true);
75
73// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 76// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74 77
75 private IMapImageService m_MapService; 78 private IMapImageService m_MapService;
@@ -82,8 +85,13 @@ namespace OpenSim.Server.Handlers.MapImage
82 85
83 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 86 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
84 { 87 {
85 byte[] result = new byte[0]; 88 ev.WaitOne();
89 lock (ev)
90 {
91 ev.Reset();
92 }
86 93
94 byte[] result = new byte[0];
87 string format = string.Empty; 95 string format = string.Empty;
88 result = m_MapService.GetMapTile(path.Trim('/'), out format); 96 result = m_MapService.GetMapTile(path.Trim('/'), out format);
89 if (result.Length > 0) 97 if (result.Length > 0)
@@ -100,6 +108,11 @@ namespace OpenSim.Server.Handlers.MapImage
100 httpResponse.ContentType = "text/plain"; 108 httpResponse.ContentType = "text/plain";
101 } 109 }
102 110
111 lock (ev)
112 {
113 ev.Set();
114 }
115
103 return result; 116 return result;
104 } 117 }
105 118