diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs index 4e6bfb88a1..2417b1ad75 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 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) { - if (mapName.Length < 2) + Util.FireAndForget(x => { - remoteClient.SendAlertMessage("Use a search string with at least 2 characters"); - return; - } - - //m_log.DebugFormat("MAP NAME=({0})", mapName); - - // Hack to get around the fact that ll V3 now drops the port from the - // map name. See https://jira.secondlife.com/browse/VWR-28570 - // - // Caller, use this magic form instead: - // secondlife://http|!!mygrid.com|8002|Region+Name/128/128 - // or url encode if possible. - // the hacks we do with this viewer... - // - string mapNameOrig = mapName; - if (mapName.Contains("|")) - mapName = mapName.Replace('|', ':'); - if (mapName.Contains("+")) - mapName = mapName.Replace('+', ' '); - if (mapName.Contains("!")) - mapName = mapName.Replace('!', '/'); - - // try to fetch from GridServer - List regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); -// if (regionInfos.Count == 0) -// remoteClient.SendAlertMessage("Hyperlink could not be established."); - - //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count); - List blocks = new List(); - - MapBlockData data; - if (regionInfos.Count > 0) - { - foreach (GridRegion info in regionInfos) + if (mapName.Length < 2) { - data = new MapBlockData(); - data.Agents = 0; - data.Access = info.Access; - if (flags == 2) // V2 sends this - data.MapImageId = UUID.Zero; - else - data.MapImageId = info.TerrainImage; - // ugh! V2-3 is very sensitive about the result being - // exactly the same as the requested name - if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+")) - data.Name = mapNameOrig; - else - data.Name = info.RegionName; - data.RegionFlags = 0; // TODO not used? - data.WaterHeight = 0; // not used - data.X = (ushort)(info.RegionLocX / Constants.RegionSize); - data.Y = (ushort)(info.RegionLocY / Constants.RegionSize); - blocks.Add(data); + remoteClient.SendAlertMessage("Use a search string with at least 2 characters"); + return; } - } - // final block, closing the search result - data = new MapBlockData(); - data.Agents = 0; - data.Access = 255; - data.MapImageId = UUID.Zero; - data.Name = mapName; - data.RegionFlags = 0; - data.WaterHeight = 0; // not used - data.X = 0; - data.Y = 0; - blocks.Add(data); + //m_log.DebugFormat("MAP NAME=({0})", mapName); - // flags are agent flags sent from the viewer. - // they have different values depending on different viewers, apparently - remoteClient.SendMapBlock(blocks, flags); + // Hack to get around the fact that ll V3 now drops the port from the + // map name. See https://jira.secondlife.com/browse/VWR-28570 + // + // Caller, use this magic form instead: + // secondlife://http|!!mygrid.com|8002|Region+Name/128/128 + // or url encode if possible. + // the hacks we do with this viewer... + // + string mapNameOrig = mapName; + if (mapName.Contains("|")) + mapName = mapName.Replace('|', ':'); + if (mapName.Contains("+")) + mapName = mapName.Replace('+', ' '); + if (mapName.Contains("!")) + mapName = mapName.Replace('!', '/'); + + // try to fetch from GridServer + List regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); + // if (regionInfos.Count == 0) + // remoteClient.SendAlertMessage("Hyperlink could not be established."); - // send extra user messages for V3 - // because the UI is very confusing - // while we don't fix the hard-coded urls - if (flags == 2) - { - if (regionInfos.Count == 0) - remoteClient.SendAgentAlertMessage("No regions found with that name.", true); - else if (regionInfos.Count == 1) - remoteClient.SendAgentAlertMessage("Region found!", false); - } + //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count); + List blocks = new List(); + + MapBlockData data; + if (regionInfos.Count > 0) + { + foreach (GridRegion info in regionInfos) + { + data = new MapBlockData(); + data.Agents = 0; + data.Access = info.Access; + if (flags == 2) // V2 sends this + data.MapImageId = UUID.Zero; + else + data.MapImageId = info.TerrainImage; + // ugh! V2-3 is very sensitive about the result being + // exactly the same as the requested name + if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+")) + data.Name = mapNameOrig; + else + data.Name = info.RegionName; + data.RegionFlags = 0; // TODO not used? + data.WaterHeight = 0; // not used + data.X = (ushort)(info.RegionLocX / Constants.RegionSize); + data.Y = (ushort)(info.RegionLocY / Constants.RegionSize); + blocks.Add(data); + } + } + + // final block, closing the search result + data = new MapBlockData(); + data.Agents = 0; + data.Access = 255; + data.MapImageId = UUID.Zero; + data.Name = mapName; + data.RegionFlags = 0; + data.WaterHeight = 0; // not used + data.X = 0; + data.Y = 0; + blocks.Add(data); + + // flags are agent flags sent from the viewer. + // they have different values depending on different viewers, apparently + remoteClient.SendMapBlock(blocks, flags); + + // send extra user messages for V3 + // because the UI is very confusing + // while we don't fix the hard-coded urls + if (flags == 2) + { + if (regionInfos.Count == 0) + remoteClient.SendAgentAlertMessage("No regions found with that name.", true); + else if (regionInfos.Count == 1) + remoteClient.SendAgentAlertMessage("Region found!", false); + } + }); } // private Scene GetClientScene(IClientAPI client) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 899e5eab20..721ac5caf7 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 private static readonly UUID STOP_UUID = UUID.Random(); private static readonly string m_mapLayerPath = "0001/"; - private OpenSim.Framework.BlockingQueue requests = new OpenSim.Framework.BlockingQueue(); + private ManualResetEvent queueEvent = new ManualResetEvent(false); + private Queue requests = new Queue(); protected Scene m_scene; private List cachedMapBlocks = new List(); @@ -71,7 +72,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap private int blacklistTimeout = 10*60*1000; // 10 minutes private byte[] myMapImageJPEG; protected volatile bool m_Enabled = false; - private Dictionary m_openRequests = new Dictionary(); private Dictionary m_blacklistedurls = new Dictionary(); private Dictionary m_blacklistedregions = new Dictionary(); private Dictionary m_cachedRegionMapItemsAddress = new Dictionary(); @@ -368,7 +368,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap st.itemtype=0; st.regionhandle=0; - requests.Enqueue(st); + lock (requests) + { + queueEvent.Set(); + requests.Enqueue(st); + } } public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, @@ -519,12 +523,26 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// public void process() { - const int MAX_ASYNC_REQUESTS = 20; + const int MAX_ASYNC_REQUESTS = 5; try { while (true) { - MapRequestState st = requests.Dequeue(1000); + MapRequestState st = new MapRequestState(); + bool valid = false; + queueEvent.WaitOne(); + lock (requests) + { + if (requests.Count > 0) + { + st = requests.Dequeue(); + valid = true; + } + if (requests.Count == 0) + queueEvent.Reset(); + } + if (!valid) + continue; // end gracefully if (st.agentID == STOP_UUID) @@ -541,14 +559,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) { - while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break - Thread.Sleep(80); +// while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break +// Thread.Sleep(500); - RequestMapItemsDelegate d = RequestMapItemsAsync; - d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null); - //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); - //RequestMapItemsCompleted(response); Interlocked.Increment(ref nAsyncRequests); + RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); } } @@ -570,110 +585,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// public void EnqueueMapItemRequest(MapRequestState state) { - requests.Enqueue(state); - } - - /// - /// Sends the mapitem response to the IClientAPI - /// - /// The OSDMap Response for the mapitem - private void RequestMapItemsCompleted(IAsyncResult iar) - { - AsyncResult result = (AsyncResult)iar; - RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate; - - OSDMap response = (OSDMap)icon.EndInvoke(iar); - - Interlocked.Decrement(ref nAsyncRequests); - - if (!response.ContainsKey("requestID")) - return; - - UUID requestID = response["requestID"].AsUUID(); - - if (requestID != UUID.Zero) + lock (requests) { - MapRequestState mrs = new MapRequestState(); - mrs.agentID = UUID.Zero; - lock (m_openRequests) - { - if (m_openRequests.ContainsKey(requestID)) - { - mrs = m_openRequests[requestID]; - m_openRequests.Remove(requestID); - } - } - - if (mrs.agentID != UUID.Zero) - { - ScenePresence av = null; - m_scene.TryGetScenePresence(mrs.agentID, out av); - if (av != null) - { - if (response.ContainsKey(mrs.itemtype.ToString())) - { - List returnitems = new List(); - OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()]; - for (int i = 0; i < itemarray.Count; i++) - { - OSDMap mapitem = (OSDMap)itemarray[i]; - mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); - returnitems.Add(mi); - } - av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags); - } - - // Service 7 (MAP_ITEM_LAND_FOR_SALE) - uint itemtype = 7; - - if (response.ContainsKey(itemtype.ToString())) - { - List returnitems = new List(); - OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; - for (int i = 0; i < itemarray.Count; i++) - { - OSDMap mapitem = (OSDMap)itemarray[i]; - mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); - returnitems.Add(mi); - } - av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags); - } - - // Service 1 (MAP_ITEM_TELEHUB) - itemtype = 1; - - if (response.ContainsKey(itemtype.ToString())) - { - List returnitems = new List(); - OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; - for (int i = 0; i < itemarray.Count; i++) - { - OSDMap mapitem = (OSDMap)itemarray[i]; - mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); - returnitems.Add(mi); - } - av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags); - } - } - } + queueEvent.Set(); + requests.Enqueue(state); } } @@ -700,8 +615,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap EnqueueMapItemRequest(st); } - private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags, - uint EstateID, bool godlike, uint itemtype, ulong regionhandle); /// /// Does the actual remote mapitem request /// This should be called from an asynchronous thread @@ -716,7 +629,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// passed in from packet /// Region we're looking up /// - private OSDMap RequestMapItemsAsync(UUID id, uint flags, + private void RequestMapItemsAsync(UUID id, uint flags, uint EstateID, bool godlike, uint itemtype, ulong regionhandle) { // m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); @@ -739,7 +652,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } if (blacklisted) - return new OSDMap(); + { + Interlocked.Decrement(ref nAsyncRequests); + return; + } UUID requestID = UUID.Random(); lock (m_cachedRegionMapItemsAddress) @@ -747,6 +663,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) httpserver = m_cachedRegionMapItemsAddress[regionhandle]; } + if (httpserver.Length == 0) { uint x = 0, y = 0; @@ -791,18 +708,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap // Can't find the http server if (httpserver.Length == 0 || blacklisted) - return new OSDMap(); - - MapRequestState mrs = new MapRequestState(); - mrs.agentID = id; - mrs.EstateID = EstateID; - mrs.flags = flags; - mrs.godlike = godlike; - mrs.itemtype=itemtype; - mrs.regionhandle = regionhandle; - - lock (m_openRequests) - m_openRequests.Add(requestID, mrs); + { + Interlocked.Decrement(ref nAsyncRequests); + return; + } WebRequest mapitemsrequest = null; try @@ -812,7 +721,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap catch (Exception e) { m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); - return new OSDMap(); + Interlocked.Decrement(ref nAsyncRequests); + return; } mapitemsrequest.Method = "POST"; @@ -826,6 +736,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap OSDMap responseMap = new OSDMap(); responseMap["requestID"] = OSD.FromUUID(requestID); +return; Stream os = null; try { // send the Post @@ -837,7 +748,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap catch (WebException ex) { m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); lock (m_blacklistedurls) { if (!m_blacklistedurls.ContainsKey(httpserver)) @@ -846,13 +756,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } catch { m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); - responseMap["connect"] = OSD.FromBoolean(false); - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } finally { @@ -873,12 +784,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } else { - return new OSDMap(); + Interlocked.Decrement(ref nAsyncRequests); + return; } } catch (WebException) { - responseMap["connect"] = OSD.FromBoolean(false); lock (m_blacklistedurls) { if (!m_blacklistedurls.ContainsKey(httpserver)) @@ -887,19 +798,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } catch { m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); - responseMap["connect"] = OSD.FromBoolean(false); lock (m_blacklistedregions) { if (!m_blacklistedregions.ContainsKey(regionhandle)) m_blacklistedregions.Add(regionhandle, Environment.TickCount); } - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } finally { @@ -918,14 +830,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap catch (Exception ex) { m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); lock (m_blacklistedregions) { if (!m_blacklistedregions.ContainsKey(regionhandle)) m_blacklistedregions.Add(regionhandle, Environment.TickCount); } - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } } @@ -939,7 +851,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } } - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + + if (id != UUID.Zero) + { + ScenePresence av = null; + m_scene.TryGetScenePresence(id, out av); + if (av != null) + { + if (responseMap.ContainsKey(itemtype.ToString())) + { + List returnitems = new List(); + OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()]; + for (int i = 0; i < itemarray.Count; i++) + { + OSDMap mapitem = (OSDMap)itemarray[i]; + mapItemReply mi = new mapItemReply(); + mi.x = (uint)mapitem["X"].AsInteger(); + mi.y = (uint)mapitem["Y"].AsInteger(); + mi.id = mapitem["ID"].AsUUID(); + mi.Extra = mapitem["Extra"].AsInteger(); + mi.Extra2 = mapitem["Extra2"].AsInteger(); + mi.name = mapitem["Name"].AsString(); + returnitems.Add(mi); + } + av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags); + } + + // Service 7 (MAP_ITEM_LAND_FOR_SALE) + itemtype = 7; + + if (responseMap.ContainsKey(itemtype.ToString())) + { + List returnitems = new List(); + OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()]; + for (int i = 0; i < itemarray.Count; i++) + { + OSDMap mapitem = (OSDMap)itemarray[i]; + mapItemReply mi = new mapItemReply(); + mi.x = (uint)mapitem["X"].AsInteger(); + mi.y = (uint)mapitem["Y"].AsInteger(); + mi.id = mapitem["ID"].AsUUID(); + mi.Extra = mapitem["Extra"].AsInteger(); + mi.Extra2 = mapitem["Extra2"].AsInteger(); + mi.name = mapitem["Name"].AsString(); + returnitems.Add(mi); + } + av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags); + } + + // Service 1 (MAP_ITEM_TELEHUB) + itemtype = 1; + + if (responseMap.ContainsKey(itemtype.ToString())) + { + List returnitems = new List(); + OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()]; + for (int i = 0; i < itemarray.Count; i++) + { + OSDMap mapitem = (OSDMap)itemarray[i]; + mapItemReply mi = new mapItemReply(); + mi.x = (uint)mapitem["X"].AsInteger(); + mi.y = (uint)mapitem["Y"].AsInteger(); + mi.id = mapitem["ID"].AsUUID(); + mi.Extra = mapitem["Extra"].AsInteger(); + mi.Extra2 = mapitem["Extra2"].AsInteger(); + mi.name = mapitem["Name"].AsString(); + returnitems.Add(mi); + } + av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags); + } + } + } } /// @@ -951,53 +934,56 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { - //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); - if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible + Util.FireAndForget(x => { - List response = new List(); - - // this should return one mapblock at most. It is triggered by a click - // on an unloaded square. - // But make sure: Look whether the one we requested is in there - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - minX * (int)Constants.RegionSize, - maxX * (int)Constants.RegionSize, - minY * (int)Constants.RegionSize, - maxY * (int)Constants.RegionSize); - - if (regions != null) + //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); + if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible { - foreach (GridRegion r in regions) + List response = new List(); + + // this should return one mapblock at most. It is triggered by a click + // on an unloaded square. + // But make sure: Look whether the one we requested is in there + List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, + minX * (int)Constants.RegionSize, + maxX * (int)Constants.RegionSize, + minY * (int)Constants.RegionSize, + maxY * (int)Constants.RegionSize); + + if (regions != null) { - if ((r.RegionLocX == minX * (int)Constants.RegionSize) && - (r.RegionLocY == minY * (int)Constants.RegionSize)) + foreach (GridRegion r in regions) { - // found it => add it to response - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r, flag); - response.Add(block); - break; + if ((r.RegionLocX == minX * (int)Constants.RegionSize) && + (r.RegionLocY == minY * (int)Constants.RegionSize)) + { + // found it => add it to response + MapBlockData block = new MapBlockData(); + MapBlockFromGridRegion(block, r, flag); + response.Add(block); + break; + } } } - } - if (response.Count == 0) - { - // response still empty => couldn't find the map-tile the user clicked on => tell the client - MapBlockData block = new MapBlockData(); - block.X = (ushort)minX; - block.Y = (ushort)minY; - block.Access = 254; // means 'simulator is offline' - response.Add(block); + if (response.Count == 0) + { + // response still empty => couldn't find the map-tile the user clicked on => tell the client + MapBlockData block = new MapBlockData(); + block.X = (ushort)minX; + block.Y = (ushort)minY; + block.Access = 254; // means 'simulator is offline' + response.Add(block); + } + // The lower 16 bits are an unsigned int16 + remoteClient.SendMapBlock(response, flag & 0xffff); } - // The lower 16 bits are an unsigned int16 - remoteClient.SendMapBlock(response, flag & 0xffff); - } - else - { - // normal mapblock request. Use the provided values - GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); - } + else + { + // normal mapblock request. Use the provided values + GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); + } + }); } protected virtual List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) @@ -1013,8 +999,15 @@ namespace OpenSim.Region.CoreModules.World.WorldMap MapBlockData block = new MapBlockData(); MapBlockFromGridRegion(block, r, flag); mapBlocks.Add(block); + if (mapBlocks.Count >= 20) + { + remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); + mapBlocks.Clear(); + Thread.Sleep(1000); + } } - remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); + if (mapBlocks.Count > 0) + remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); return mapBlocks; } diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index fb85d1ce1c..4502b7d9f7 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -29,6 +29,7 @@ using System; using System.IO; using System.Net; using System.Reflection; +using System.Threading; using Nini.Config; using log4net; @@ -70,6 +71,8 @@ namespace OpenSim.Server.Handlers.MapImage class MapServerGetHandler : BaseStreamHandler { + public static ManualResetEvent ev = new ManualResetEvent(true); + // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IMapImageService m_MapService; @@ -82,8 +85,13 @@ namespace OpenSim.Server.Handlers.MapImage public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - byte[] result = new byte[0]; + ev.WaitOne(); + lock (ev) + { + ev.Reset(); + } + byte[] result = new byte[0]; string format = string.Empty; result = m_MapService.GetMapTile(path.Trim('/'), out format); if (result.Length > 0) @@ -100,6 +108,11 @@ namespace OpenSim.Server.Handlers.MapImage httpResponse.ContentType = "text/plain"; } + lock (ev) + { + ev.Set(); + } + return result; }