diff options
author | Melanie | 2012-07-08 06:06:33 +0200 |
---|---|---|
committer | Melanie | 2012-07-08 06:06:33 +0200 |
commit | d3b778ebbe617a37a32c866101c75284dad8f15a (patch) | |
tree | 9e1b8dfdd6ae21607fead5149486494a5ec84374 /OpenSim | |
parent | Change semantics of FromXML on vehicle data to make the serializer a bit cleaner (diff) | |
download | opensim-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')
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 | ||
739 | return; | ||
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; | |||
29 | using System.IO; | 29 | using System.IO; |
30 | using System.Net; | 30 | using System.Net; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Threading; | ||
32 | 33 | ||
33 | using Nini.Config; | 34 | using Nini.Config; |
34 | using log4net; | 35 | using 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 | ||