From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../Grid/LocalGridServiceConnector.cs | 164 ++-- .../ServiceConnectorsOut/Grid/RegionCache.cs | 102 --- .../ServiceConnectorsOut/Grid/RegionInfoCache.cs | 965 +++++++++++++++++++-- .../Grid/RemoteGridServiceConnector.cs | 154 ++-- .../Grid/Tests/GridConnectorsTests.cs | 6 +- 5 files changed, 1070 insertions(+), 321 deletions(-) delete mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs (limited to 'OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs index 1f782f5..d220568 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs @@ -51,7 +51,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]"; private IGridService m_GridService; - private Dictionary m_LocalCache = new Dictionary(); + private RegionInfoCache m_RegionInfoCache; + private HashSet m_scenes = new HashSet(); private bool m_Enabled; @@ -63,12 +64,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public LocalGridServicesConnector(IConfigSource source) { m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader); - InitialiseService(source); + InitialiseService(source, null); + } + + public LocalGridServicesConnector(IConfigSource source, RegionInfoCache regionInfoCache) + { + m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly with cache.", LogHeader); + InitialiseService(source, regionInfoCache); } #region ISharedRegionModule - public Type ReplaceableInterface + public Type ReplaceableInterface { get { return null; } } @@ -86,19 +93,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid string name = moduleConfig.GetString("GridServices", ""); if (name == Name) { - InitialiseService(source); - m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled"); + if(InitialiseService(source, null)) + m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled"); } } } - private void InitialiseService(IConfigSource source) + private bool InitialiseService(IConfigSource source, RegionInfoCache ric) { + if(ric == null && m_RegionInfoCache == null) + m_RegionInfoCache = new RegionInfoCache(); + else + m_RegionInfoCache = ric; + IConfig config = source.Configs["GridService"]; if (config == null) { m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini"); - return; + return false; } string serviceDll = config.GetString("LocalServiceModule", String.Empty); @@ -106,7 +118,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid if (serviceDll == String.Empty) { m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService"); - return; + return false; } Object[] args = new Object[] { source }; @@ -117,19 +129,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid if (m_GridService == null) { m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service"); - return; + return false; } m_Enabled = true; + return true; } public void PostInitialise() { - // FIXME: We will still add this command even if we aren't enabled since RemoteGridServiceConnector - // will have instantiated us directly. - MainConsole.Instance.Commands.AddCommand("Regions", false, "show neighbours", - "show neighbours", - "Shows the local regions' neighbours", HandleShowNeighboursCommand); } public void Close() @@ -141,15 +149,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid if (!m_Enabled) return; - scene.RegisterModuleInterface(this); - - lock (m_LocalCache) + lock(m_scenes) { - if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID)) - m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!"); - else - m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene)); + if(!m_scenes.Contains(scene)) + m_scenes.Add(scene); } + scene.RegisterModuleInterface(this); + + GridRegion r = new GridRegion(scene.RegionInfo); + m_RegionInfoCache.CacheLocal(r); + + scene.EventManager.OnRegionUp += OnRegionUp; } public void RemoveRegion(Scene scene) @@ -157,11 +167,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid if (!m_Enabled) return; - lock (m_LocalCache) + lock(m_scenes) { - m_LocalCache[scene.RegionInfo.RegionID].Clear(); - m_LocalCache.Remove(scene.RegionInfo.RegionID); + if(m_scenes.Contains(scene)) + m_scenes.Remove(scene); } + + m_RegionInfoCache.Remove(scene.RegionInfo.ScopeID, scene.RegionInfo.RegionHandle); + scene.EventManager.OnRegionUp -= OnRegionUp; } public void RegionLoaded(Scene scene) @@ -172,6 +185,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid #region IGridService + private void OnRegionUp(GridRegion region) + { + // This shouldn't happen + if (region == null) + return; + + m_RegionInfoCache.CacheNearNeighbour(region.ScopeID, region); + } + public string RegisterRegion(UUID scopeID, GridRegion regionInfo) { return m_GridService.RegisterRegion(scopeID, regionInfo); @@ -184,12 +206,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public List GetNeighbours(UUID scopeID, UUID regionID) { - return m_GridService.GetNeighbours(scopeID, regionID); + return m_GridService.GetNeighbours(scopeID, regionID); } public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) { - return m_GridService.GetRegionByUUID(scopeID, regionID); + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache); + if (inCache) + return rinfo; + + rinfo = m_GridService.GetRegionByUUID(scopeID, regionID); + if(rinfo != null) + m_RegionInfoCache.Cache(scopeID, rinfo); + return rinfo; } // Get a region given its base coordinates. @@ -197,59 +227,30 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid // be the base coordinate of the region. public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) { - GridRegion region = null; - uint regionX = Util.WorldToRegionLoc((uint)x); - uint regionY = Util.WorldToRegionLoc((uint)y); - // Sanity check - if ((Util.RegionToWorldLoc(regionX) != (uint)x) || (Util.RegionToWorldLoc(regionY) != (uint)y)) - { - m_log.WarnFormat("{0} GetRegionByPosition. Bad position requested: not the base of the region. Requested Pos=<{1},{2}>, Should Be=<{3},{4}>", - LogHeader, x, y, Util.RegionToWorldLoc(regionX), Util.RegionToWorldLoc(regionY)); - } - - // First see if it's a neighbour, even if it isn't on this sim. - // Neighbour data is cached in memory, so this is fast - - lock (m_LocalCache) - { - foreach (RegionCache rcache in m_LocalCache.Values) - { - region = rcache.GetRegionByPosition(x, y); - if (region != null) - { - m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache (of region {2}). Pos=<{3},{4}>", - LogHeader, region.RegionName, rcache.RegionName, - Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY)); - break; - } - } - } + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID, (uint)x, (uint)y, out inCache); + if (inCache) + return rinfo; // Then try on this sim (may be a lookup in DB if this is using MySql). - if (region == null) - { - region = m_GridService.GetRegionByPosition(scopeID, x, y); - - if (region == null) - { - m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>", - LogHeader, regionX, regionY); - } - else - { - m_log.DebugFormat("{0} GetRegionByPosition. Got region {1} from grid service. Pos=<{2},{3}>", - LogHeader, region.RegionName, - Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY)); - } - } - - return region; + rinfo = m_GridService.GetRegionByPosition(scopeID, x, y); + if(rinfo != null) + m_RegionInfoCache.Cache(scopeID, rinfo); + return rinfo; } public GridRegion GetRegionByName(UUID scopeID, string regionName) { - return m_GridService.GetRegionByName(scopeID, regionName); + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionName, out inCache); + if (inCache) + return rinfo; + + rinfo = m_GridService.GetRegionByName(scopeID, regionName); + if(rinfo != null) + m_RegionInfoCache.Cache(scopeID, rinfo); + return rinfo; } public List GetRegionsByName(UUID scopeID, string name, int maxNumber) @@ -281,7 +282,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { return m_GridService.GetHyperlinks(scopeID); } - + public int GetRegionFlags(UUID scopeID, UUID regionID) { return m_GridService.GetRegionFlags(scopeID, regionID); @@ -294,22 +295,5 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid #endregion - public void HandleShowNeighboursCommand(string module, string[] cmdparams) - { - System.Text.StringBuilder caps = new System.Text.StringBuilder(); - - lock (m_LocalCache) - { - foreach (KeyValuePair kvp in m_LocalCache) - { - caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key); - List regions = kvp.Value.GetNeighbours(); - foreach (GridRegion r in regions) - caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY)); - } - } - - MainConsole.Instance.Output(caps.ToString()); - } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs deleted file mode 100644 index ae76288..0000000 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; - -using OpenMetaverse; -using log4net; - -namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid -{ - public class RegionCache - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - private Dictionary m_neighbours = new Dictionary(); - - public string RegionName - { - get { return m_scene.RegionInfo.RegionName; } - } - - public RegionCache(Scene s) - { - m_scene = s; - m_scene.EventManager.OnRegionUp += OnRegionUp; - } - - private void OnRegionUp(GridRegion otherRegion) - { - // This shouldn't happen - if (otherRegion == null) - return; - - m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}", - m_scene.RegionInfo.RegionName, otherRegion.RegionName, Util.WorldToRegionLoc((uint)otherRegion.RegionLocX), Util.WorldToRegionLoc((uint)otherRegion.RegionLocY)); - - m_neighbours[otherRegion.RegionHandle] = otherRegion; - } - - public void Clear() - { - m_scene.EventManager.OnRegionUp -= OnRegionUp; - m_neighbours.Clear(); - } - - public List GetNeighbours() - { - return new List(m_neighbours.Values); - } - - // Get a region given its base coordinates (in meters). - // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST - // be the base coordinate of the region. - // The snapping is technically unnecessary but is harmless because regions are always - // multiples of the legacy region size (256). - public GridRegion GetRegionByPosition(int x, int y) - { - uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize; - uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize; - ulong handle = Util.RegionWorldLocToHandle(xsnap, ysnap); - - if (m_neighbours.ContainsKey(handle)) - return m_neighbours[handle]; - - return null; - } - } -} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs index be8a9a2..f6fff58 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs @@ -26,6 +26,8 @@ */ using System; using System.Reflection; +using System.Threading; +using System.Runtime.InteropServices; using System.Collections.Generic; using OpenSim.Framework; using OpenSim.Services.Interfaces; @@ -37,82 +39,68 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { public class RegionInfoCache { - private const double CACHE_EXPIRATION_SECONDS = 300.0; // 5 minutes + private const float CACHE_EXPIRATION_SECONDS = 120; // 2 minutes opensim regions change a lot // private static readonly ILog m_log = // LogManager.GetLogger( // MethodBase.GetCurrentMethod().DeclaringType); - - internal struct ScopedRegionUUID + + private static RegionsExpiringCache m_Cache; + private int numberInstances; + + public RegionInfoCache() { - public UUID m_scopeID; - public UUID m_regionID; - public ScopedRegionUUID(UUID scopeID, UUID regionID) - { - m_scopeID = scopeID; - m_regionID = regionID; - } + if(m_Cache == null) + m_Cache = new RegionsExpiringCache(); + numberInstances++; } - - internal struct ScopedRegionName + + public void Cache(GridRegion rinfo) { - public UUID m_scopeID; - public string m_name; - public ScopedRegionName(UUID scopeID, string name) - { - m_scopeID = scopeID; - m_name = name; - } + if (rinfo != null) + this.Cache(rinfo.ScopeID, rinfo); } - internal struct ScopedRegionPosition + public void Cache(UUID scopeID, GridRegion rinfo) { - public UUID m_scopeID; - public ulong m_regionHandle; - public ScopedRegionPosition(UUID scopeID, ulong handle) - { - m_scopeID = scopeID; - m_regionHandle = handle; - } - } + if (rinfo == null) + return; - private ExpiringCache m_UUIDCache; - private ExpiringCache m_NameCache; - private ExpiringCache m_PositionCache; + m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS); + } - public RegionInfoCache() + public void CacheLocal(GridRegion rinfo) { - m_UUIDCache = new ExpiringCache(); - m_NameCache = new ExpiringCache(); - m_PositionCache = new ExpiringCache(); + if (rinfo == null) + return; + + m_Cache.AddOrUpdate(rinfo.ScopeID, rinfo, 1e7f); } - public void Cache(GridRegion rinfo) + public void CacheNearNeighbour(UUID scopeID, GridRegion rinfo) { - if (rinfo != null) - this.Cache(rinfo.ScopeID,rinfo.RegionID,rinfo); + if (rinfo == null) + return; + + m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS); } - - public void Cache(UUID scopeID, UUID regionID, GridRegion rinfo) + + public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds) { - // for now, do not cache negative results; this is because - // we need to figure out how to handle regions coming online - // in a timely way if (rinfo == null) return; - - ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); - - // Cache even null accounts - m_UUIDCache.AddOrUpdate(id, rinfo, CACHE_EXPIRATION_SECONDS); - if (rinfo != null) - { - ScopedRegionName name = new ScopedRegionName(scopeID,rinfo.RegionName); - m_NameCache.AddOrUpdate(name, id, CACHE_EXPIRATION_SECONDS); - ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, rinfo.RegionHandle); - m_PositionCache.AddOrUpdate(pos, rinfo, CACHE_EXPIRATION_SECONDS); - } + m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds); + } + + public void Remove(UUID scopeID, GridRegion rinfo) + { + m_Cache.Remove(scopeID, rinfo); + } + + public void Remove(UUID scopeID, ulong regionHandle) + { + m_Cache.Remove(scopeID, regionHandle); } public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) @@ -120,8 +108,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid inCache = false; GridRegion rinfo = null; - ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); - if (m_UUIDCache.TryGetValue(id, out rinfo)) + if (m_Cache.TryGetValue(scopeID, regionID, out rinfo)) { inCache = true; return rinfo; @@ -135,8 +122,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid inCache = false; GridRegion rinfo = null; - ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, handle); - if (m_PositionCache.TryGetValue(pos, out rinfo)) + if (m_Cache.TryGetValue(scopeID, handle, out rinfo)) { inCache = true; return rinfo; @@ -145,25 +131,868 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid return null; } - public GridRegion Get(UUID scopeID, string name, out bool inCache) { inCache = false; - ScopedRegionName sname = new ScopedRegionName(scopeID,name); + GridRegion rinfo = null; + if (m_Cache.TryGetValue(scopeID, name, out rinfo)) + { + inCache = true; + return rinfo; + } + + return null; + } + + public GridRegion Get(UUID scopeID, uint x, uint y, out bool inCache) + { + inCache = false; + + GridRegion rinfo = null; + if (m_Cache.TryGetValue(scopeID, x, y, out rinfo)) + { + inCache = true; + return rinfo; + } + + return null; + } + } + + // dont care about endianess + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public class fastRegionHandle + { + [FieldOffset(0)] public ulong handle; + [FieldOffset(0)] public uint y; + [FieldOffset(4)] public uint x; + + public fastRegionHandle(ulong h) + { + handle = h; + } + + public fastRegionHandle(uint px, uint py) + { + y = py & 0xffffff00; + x = px & 0xffffff00; + } + // actually do care + public ulong toHandle() + { + if(BitConverter.IsLittleEndian) + return handle; + return (ulong) x << 32 | (ulong)y ; + } + + public static bool operator ==(fastRegionHandle value1, fastRegionHandle value2) + { + return value1.handle == value2.handle; + } + public static bool operator !=(fastRegionHandle value1, fastRegionHandle value2) + { + return value1.handle != value2.handle; + } + public override int GetHashCode() + { + return handle.GetHashCode(); + } + public override bool Equals(Object obj) + { + if(obj == null) + return false; + fastRegionHandle p = obj as fastRegionHandle; + return p.handle == handle; + } + } + +/* + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public class regionHandle + { + [FieldOffset(0)] private ulong handle; + [FieldOffset(0)] public uint a; + [FieldOffset(4)] public uint b; + + public regionHandle(ulong h) + { + handle = h; + } + + public regionHandle(uint px, uint py) + { + if(BitConverter.IsLittleEndian) + { + a = py & 0xffffff00; + b = px & 0xffffff00; + } + else + { + a = px & 0xffffff00; + b = py & 0xffffff00; + } + } + + public uint x + { + get + { + if(BitConverter.IsLittleEndian) + return b; + return a; + } + set + { + if(BitConverter.IsLittleEndian) + b = value & 0xffffff00; + else + a = value & 0xffffff00; + } + } + + public uint y + { + get + { + if(BitConverter.IsLittleEndian) + return a; + return b; + } + set + { + if(BitConverter.IsLittleEndian) + a = value; + else + b = value; + } + } + + public static bool operator ==(regionHandle value1, regionHandle value2) + { + return value1.handle == value2.handle; + } + public static bool operator !=(regionHandle value1, regionHandle value2) + { + return value1.handle != value2.handle; + } + public override int GetHashCode() + { + return handle.GetHashCode(); + } + public override bool Equals(Object obj) + { + if(obj == null) + return false; + regionHandle p = obj as regionHandle; + return p.handle == handle; + } + } +*/ + + public class RegionInfoForScope + { + public const ulong HANDLEMASK = 0xffffff00ffffff00ul; + public const ulong HANDLECOORDMASK = 0xffffff00ul; + + private Dictionary storage; + private Dictionary expires; + private Dictionary byname; + private Dictionary byuuid; + // includes handles to the inside of large regions + private Dictionary innerHandles = new Dictionary(); + + public RegionInfoForScope() + { + storage = new Dictionary(); + expires = new Dictionary(); + byname = new Dictionary(); + byuuid = new Dictionary(); + } + + public RegionInfoForScope(GridRegion region, DateTime expire) + { + storage = new Dictionary(); + expires = new Dictionary(); + byname = new Dictionary(); + byuuid = new Dictionary(); + + ulong handle = region.RegionHandle & HANDLEMASK; + storage[handle] = region; + expires[handle] = expire; + byname[region.RegionName] = handle; + byuuid[region.RegionID] = handle; + addToInner(region); + } + + public void Add(GridRegion region, DateTime expire) + { + ulong handle = region.RegionHandle & HANDLEMASK; + + if(storage != null && storage.ContainsKey(handle)) + return; + + if(storage == null) + storage = new Dictionary(); + if(expires == null) + expires = new Dictionary(); + if(byname == null) + byname = new Dictionary(); + if(byuuid == null) + byuuid = new Dictionary(); + + storage[handle] = region; + expires[handle] = expire; + byname[region.RegionName] = handle; + byuuid[region.RegionID] = handle; + + addToInner(region); + } + + public void AddUpdate(GridRegion region, DateTime expire) + { + if(storage == null) + storage = new Dictionary(); + if(expires == null) + expires = new Dictionary(); + if(byname == null) + byname = new Dictionary(); + if(byuuid == null) + byuuid = new Dictionary(); + + ulong handle = region.RegionHandle & HANDLEMASK; - ScopedRegionUUID id; - if (m_NameCache.TryGetValue(sname, out id)) + if(expires.ContainsKey(handle)) { - GridRegion rinfo = null; - if (m_UUIDCache.TryGetValue(id, out rinfo)) + if(expires[handle] < expire) + expires[handle] = expire; + if(storage.ContainsKey(handle)) { - inCache = true; - return rinfo; + GridRegion oldr = storage[handle]; + if (oldr.RegionSizeX != region.RegionSizeX + || oldr.RegionSizeY != region.RegionSizeY) + { + removeFromInner(oldr); + addToInner(region); + } } } - + else + { + expires[handle] = expire; + addToInner(region); + } + storage[handle] = region; + byname[region.RegionName] = handle; + byuuid[region.RegionID] = handle; + } + + public void Remove(GridRegion region) + { + if(region == null) + return; + + if(byname != null) + byname.Remove(region.RegionName); + if(byuuid != null) + byuuid.Remove(region.RegionID); + + ulong handle = region.RegionHandle & HANDLEMASK; + if(storage != null) + { + if(storage.ContainsKey(handle)) + { + storage[handle] = null; + storage.Remove(handle); + } + } + removeFromInner(region); + if(expires != null) + { + expires.Remove(handle); + if(expires.Count == 0) + Clear(); + } + } + + public void Remove(ulong handle) + { + handle &= HANDLEMASK; + + if(storage != null) + { + if(storage.ContainsKey(handle)) + { + GridRegion r = storage[handle]; + if(byname != null) + byname.Remove(r.RegionName); + if(byuuid != null) + byuuid.Remove(r.RegionID); + removeFromInner(r); + storage[handle] = null; + } + storage.Remove(handle); + } + if(expires != null) + { + expires.Remove(handle); + if(expires.Count == 0) + Clear(); + } + } + + public void Clear() + { + if(expires != null) + expires.Clear(); + if(storage != null) + storage.Clear(); + if(byname != null) + byname.Clear(); + if(byuuid != null) + byuuid.Clear(); + byname = null; + byuuid = null; + storage = null; + expires = null; + innerHandles.Clear(); + } + + public bool Contains(GridRegion region) + { + if(storage == null) + return false; + if(region == null) + return false; + + ulong handle = region.RegionHandle & HANDLEMASK; + return storage.ContainsKey(handle); + } + + public bool Contains(ulong handle) + { + if(storage == null) + return false; + + handle &= HANDLEMASK; + return storage.ContainsKey(handle); + } + + public GridRegion get(ulong handle) + { + if(storage == null) + return null; + + handle &= HANDLEMASK; + if(storage.ContainsKey(handle)) + return storage[handle]; + + if(!innerHandles.ContainsKey(handle)) + return null; + + ulong rhandle = innerHandles[handle]; + if(storage.ContainsKey(rhandle)) + return storage[rhandle]; + return null; } + + public GridRegion get(string name) + { + if(byname == null || !byname.ContainsKey(name)) + return null; + + ulong handle = byname[name]; + if(storage.ContainsKey(handle)) + return storage[handle]; + return null; + } + + public GridRegion get(UUID id) + { + if(byuuid == null || !byuuid.ContainsKey(id)) + return null; + + ulong handle = byuuid[id]; + if(storage.ContainsKey(handle)) + return storage[handle]; + return null; + } + + public GridRegion get(uint x, uint y) + { + if(storage == null) + return null; + + // look for a handle first this should find normal size regions + ulong handle = (ulong)x & HANDLECOORDMASK; + handle <<= 32; + handle |= ((ulong)y & HANDLECOORDMASK); + + if(storage.ContainsKey(handle)) + return storage[handle]; + + if(!innerHandles.ContainsKey(handle)) + return null; + + ulong rhandle = innerHandles[handle]; + if(!storage.ContainsKey(rhandle)) + return null; + + GridRegion r = storage[rhandle]; + if(r == null) + return null; + + // extra check, possible redundant + + int test = r.RegionLocX; + if(x < test) + return null; + test += r.RegionSizeX; + if(x >= test) + return null; + test = r.RegionLocY; + if (y < test) + return null; + test += r.RegionSizeY; + if (y < test) + return r; + +/* + // next do the harder work + foreach(KeyValuePair kvp in storage) + { + GridRegion r = kvp.Value; + if(r == null) // ?? + continue; + + int test = r.RegionLocX; + if(x < test) + continue; + test += r.RegionSizeX; + if(x >= test) + continue; + test = r.RegionLocY; + if (y < test) + continue; + test += r.RegionSizeY; + if (y < test) + return r; + } +*/ + return null; + } + + public int expire(DateTime now ) + { + if(expires == null || expires.Count == 0) + return 0; + + int expiresCount = expires.Count; + List toexpire = new List(); + + foreach(KeyValuePair kvp in expires) + { + if(kvp.Value < now) + toexpire.Add(kvp.Key); + } + + int toexpireCount = toexpire.Count; + if(toexpireCount == 0) + return expiresCount; + + if(toexpireCount == expiresCount) + { + Clear(); + return 0; + } + + if(storage != null) + { + ulong h; + for(int i = 0; i < toexpireCount; i++) + { + h = toexpire[i]; + if(storage.ContainsKey(h)) + { + GridRegion r = storage[h]; + if(byname != null) + byname.Remove(r.RegionName); + if(byuuid != null) + byuuid.Remove(r.RegionID); + removeFromInner(r); + + storage[h] = null; + storage.Remove(h); + } + if(expires != null) + expires.Remove(h); + } + } + else + { + Clear(); + return 0; + } + + expiresCount = expires.Count; + if(expiresCount == 0) + { + byname = null; + byuuid = null; + storage = null; + expires = null; + return 0; + } + + return expiresCount; + } + + public int Count() + { + if(byname == null) + return 0; + else + return byname.Count; + } + + private void addToInner(GridRegion region) + { + int rsx = region.RegionSizeX; + int rsy = region.RegionSizeY; + + if(rsx < 512 && rsy < 512) + return; + + rsx >>= 8; + rsy >>= 8; + + ulong handle = region.RegionHandle & HANDLEMASK; + fastRegionHandle fh = new fastRegionHandle(handle); + uint startY = fh.y; + for(int i = 0; i < rsx; i++) + { + for(int j = 0; j < rsy ; j++) + { + innerHandles[fh.toHandle()] = handle; + fh.y += 256; + } + + fh.y = startY; + fh.x += 256; + } + } + + private void removeFromInner(GridRegion region) + { + int rsx = region.RegionSizeX; + int rsy = region.RegionSizeY; + + if(rsx < 512 && rsy < 512) + return; + + rsx >>= 8; + rsy >>= 8; + ulong handle = region.RegionHandle & HANDLEMASK; + fastRegionHandle fh = new fastRegionHandle(handle); + uint startY = fh.y; + for(int i = 0; i < rsx; i++) + { + for(int j = 0; j < rsy ; j++) + { + innerHandles.Remove(fh.toHandle()); + fh.y += 256; + } + + fh.y = startY; + fh.x += 256; + } + } + } + + public class RegionsExpiringCache + { + const double CACHE_PURGE_TIME = 60000; // milliseconds + const int MAX_LOCK_WAIT = 10000; // milliseconds + + /// For thread safety + object syncRoot = new object(); + /// For thread safety + object isPurging = new object(); + + Dictionary InfobyScope = new Dictionary(); + private System.Timers.Timer timer = new System.Timers.Timer(CACHE_PURGE_TIME); + + public RegionsExpiringCache() + { + timer.Elapsed += PurgeCache; + timer.Start(); + } + + public bool AddOrUpdate(UUID scope, GridRegion region, float expirationSeconds) + { + if(region == null) + return false; + + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + try + { + DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds); + + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + { + ris = new RegionInfoForScope(region, expire); + InfobyScope[scope] = ris; + } + else + ris.AddUpdate(region, expire); + + return true; + } + finally { Monitor.Exit(syncRoot); } + } + + public void Clear() + { + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + try + { + foreach(RegionInfoForScope ris in InfobyScope.Values) + ris.Clear(); + InfobyScope.Clear(); + } + finally { Monitor.Exit(syncRoot); } + } + + public bool Contains(UUID scope, GridRegion region) + { + if(region == null) + return false; + + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + + return ris.Contains(region); + } + finally { Monitor.Exit(syncRoot); } + } + + public bool Contains(UUID scope, ulong handle) + { + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + + return ris.Contains(handle); + } + finally { Monitor.Exit(syncRoot); } + } + + public int Count() + { + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + try + { + int count = 0; + foreach(RegionInfoForScope ris in InfobyScope.Values) + count += ris.Count(); + return count; + } + finally { Monitor.Exit(syncRoot); } + } + + public bool Remove(UUID scope, ulong handle) + { + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + + ris.Remove(handle); + if(ris.Count() == 0) + InfobyScope.Remove(scope); + return true; + } + finally { Monitor.Exit(syncRoot); } + } + + public bool Remove(UUID scope, GridRegion region) + { + if(region == null) + return false; + + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + + ris.Remove(region); + if(ris.Count() == 0) + InfobyScope.Remove(scope); + return true; + } + finally { Monitor.Exit(syncRoot); } + } + + public bool TryGetValue(UUID scope, ulong handle, out GridRegion value) + { + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + value = null; + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + value = ris.get(handle); + } + finally { Monitor.Exit(syncRoot); } + + return value != null; + } + + public bool TryGetValue(UUID scope, string name, out GridRegion value) + { + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + value = null; + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + value = ris.get(name); + } + finally { Monitor.Exit(syncRoot); } + + return value != null; + } + + public bool TryGetValue(UUID scope, UUID id, out GridRegion value) + { + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + value = null; + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + value = ris.get(id); + } + finally { Monitor.Exit(syncRoot); } + + return value != null; + } + + // gets a region that contains world position (x,y) + // hopefull will not take ages + public bool TryGetValue(UUID scope, uint x, uint y, out GridRegion value) + { + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + value = null; + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + + value = ris.get(x, y); + } + finally { Monitor.Exit(syncRoot); } + + return value != null; + } + + public bool Update(UUID scope, GridRegion region, double expirationSeconds) + { + if(region == null) + return false; + + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); + + try + { + RegionInfoForScope ris = null; + if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) + return false; + + DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds); + ris.AddUpdate(region,expire); + return true; + } + finally { Monitor.Exit(syncRoot); } + } + + /// + /// Purges expired objects from the cache. Called automatically by the purge timer. + /// + private void PurgeCache(object sender, System.Timers.ElapsedEventArgs e) + { + // Only let one thread purge at once - a buildup could cause a crash + // This could cause the purge to be delayed while there are lots of read/write ops + // happening on the cache + if (!Monitor.TryEnter(isPurging)) + return; + + DateTime now = DateTime.UtcNow; + + try + { + // If we fail to acquire a lock on the synchronization root after MAX_LOCK_WAIT, skip this purge cycle + if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) + return; + try + { + List expiredscopes = new List(); + + foreach (KeyValuePair kvp in InfobyScope) + { + if (kvp.Value.expire(now) == 0) + expiredscopes.Add(kvp.Key); + } + + if (expiredscopes.Count > 0) + { + foreach (UUID sid in expiredscopes) + { + InfobyScope[sid] = null; + InfobyScope.Remove(sid); + } + } + } + finally { Monitor.Exit(syncRoot); } + } + finally { Monitor.Exit(isPurging); } + } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs index 85073fc..ee17093 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs @@ -52,12 +52,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid MethodBase.GetCurrentMethod().DeclaringType); private bool m_Enabled = false; + private string m_ThisGatekeeper = string.Empty; private IGridService m_LocalGridService; private IGridService m_RemoteGridService; - private RegionInfoCache m_RegionInfoCache = new RegionInfoCache(); - + private RegionInfoCache m_RegionInfoCache; + public RemoteGridServicesConnector() { } @@ -69,7 +70,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid #region ISharedRegionmodule - public Type ReplaceableInterface + public Type ReplaceableInterface { get { return null; } } @@ -87,38 +88,57 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid string name = moduleConfig.GetString("GridServices", ""); if (name == Name) { - InitialiseServices(source); - m_Enabled = true; - m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled"); + if(InitialiseServices(source)) + { + m_Enabled = true; + m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled"); + } } } } - private void InitialiseServices(IConfigSource source) + private bool InitialiseServices(IConfigSource source) { IConfig gridConfig = source.Configs["GridService"]; if (gridConfig == null) { m_log.Error("[REMOTE GRID CONNECTOR]: GridService missing from OpenSim.ini"); - return; + return false; } string networkConnector = gridConfig.GetString("NetworkConnector", string.Empty); if (networkConnector == string.Empty) { m_log.Error("[REMOTE GRID CONNECTOR]: Please specify a network connector under [GridService]"); - return; + return false; } - Object[] args = new Object[] { source }; + Object[] args = new Object[] { source }; m_RemoteGridService = ServerUtils.LoadPlugin(networkConnector, args); - m_LocalGridService = new LocalGridServicesConnector(source); - } + m_LocalGridService = new LocalGridServicesConnector(source, m_RegionInfoCache); + if (m_LocalGridService == null) + { + m_log.Error("[REMOTE GRID CONNECTOR]: failed to load local connector"); + return false; + } + + if(m_RegionInfoCache == null) + m_RegionInfoCache = new RegionInfoCache(); + + m_ThisGatekeeper = Util.GetConfigVarFromSections(source, "GatekeeperURI", + new string[] { "Startup", "Hypergrid", "GridService" }, String.Empty); + // Legacy. Remove soon! + m_ThisGatekeeper = gridConfig.GetString("Gatekeeper", m_ThisGatekeeper); + + Util.checkServiceURI(m_ThisGatekeeper, out m_ThisGatekeeper); + + return true; + } public void PostInitialise() { - if (m_LocalGridService != null) + if (m_Enabled) ((ISharedRegionModule)m_LocalGridService).PostInitialise(); } @@ -129,15 +149,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public void AddRegion(Scene scene) { if (m_Enabled) + { scene.RegisterModuleInterface(this); - - if (m_LocalGridService != null) ((ISharedRegionModule)m_LocalGridService).AddRegion(scene); + } } public void RemoveRegion(Scene scene) { - if (m_LocalGridService != null) + if (m_Enabled) ((ISharedRegionModule)m_LocalGridService).RemoveRegion(scene); } @@ -174,16 +194,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) { - bool inCache = false; - GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache); - if (inCache) + GridRegion rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); + if (rinfo != null) return rinfo; - - rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); - if (rinfo == null) - rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID); - m_RegionInfoCache.Cache(scopeID,regionID,rinfo); + rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID); + m_RegionInfoCache.Cache(scopeID, rinfo); return rinfo; } @@ -193,51 +209,56 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid // The coordinates are world coords (meters), NOT region units. public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) { - ulong regionHandle = Util.RegionWorldLocToHandle((uint)x, (uint)y); - uint regionX = Util.WorldToRegionLoc((uint)x); - uint regionY = Util.WorldToRegionLoc((uint)y); - - // Sanity check - if ((Util.RegionToWorldLoc(regionX) != (uint)x) || (Util.RegionToWorldLoc(regionY) != (uint)y)) + GridRegion rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y); + if (rinfo != null) { - m_log.WarnFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Bad position requested: not the base of the region. Requested Pos=<{0},{1}>, Should Be=<{2},{3}>", - x, y, Util.RegionToWorldLoc(regionX), Util.RegionToWorldLoc(regionY)); - } - - bool inCache = false; - GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionHandle, out inCache); - if (inCache) - { - //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Found region {0} in cache. Pos=<{1},{2}>, RegionHandle={3}", - // (rinfo == null) ? "" : rinfo.RegionName, regionX, regionY, (rinfo == null) ? regionHandle : rinfo.RegionHandle); +// m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Found region {0} on local. Pos=<{1},{2}>, RegionHandle={3}", +// rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle); return rinfo; } - rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y); - if (rinfo == null) - rinfo = m_RemoteGridService.GetRegionByPosition(scopeID, x, y); + rinfo = m_RemoteGridService.GetRegionByPosition(scopeID, x, y); - m_RegionInfoCache.Cache(rinfo); - - //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}", - // (rinfo == null) ? "" : rinfo.RegionName, regionX, regionY, (rinfo == null) ? regionHandle : rinfo.RegionHandle); + if (rinfo == null) + { +// uint regionX = Util.WorldToRegionLoc((uint)x); +// uint regionY = Util.WorldToRegionLoc((uint)y); +// m_log.WarnFormat("[REMOTE GRID CONNECTOR]: Requested region {0}-{1} not found", regionX, regionY); + } + else + { + m_RegionInfoCache.Cache(scopeID, rinfo); +// m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}", +// rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle); + } return rinfo; } - public GridRegion GetRegionByName(UUID scopeID, string regionName) + public GridRegion GetRegionByName(UUID scopeID, string name) { - bool inCache = false; - GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionName, out inCache); - if (inCache) + GridRegion rinfo = m_LocalGridService.GetRegionByName(scopeID, name); + if (rinfo != null) return rinfo; - - rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); - if (rinfo == null) - rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName); - // can't cache negative results for name lookups - m_RegionInfoCache.Cache(rinfo); + // HG urls should not get here, strip them + // side effect is that local regions with same name as HG may also be found + // this mb good or bad + string regionName = name; + if(name.Contains(".")) + { + if(string.IsNullOrWhiteSpace(m_ThisGatekeeper)) + return rinfo; // no HG + + string regionURI = ""; + if(!Util.buildHGRegionURI(name, out regionURI, out regionName) || string.IsNullOrWhiteSpace(regionName)) + return rinfo; // invalid + if(m_ThisGatekeeper != regionURI) + return rinfo; // not local grid + } + + rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName); + m_RegionInfoCache.Cache(scopeID, rinfo); return rinfo; } @@ -245,7 +266,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { List rinfo = m_LocalGridService.GetRegionsByName(scopeID, name, maxNumber); //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Local GetRegionsByName {0} found {1} regions", name, rinfo.Count); - List grinfo = m_RemoteGridService.GetRegionsByName(scopeID, name, maxNumber); + + // HG urls should not get here, strip them + // side effect is that local regions with same name as HG may also be found + // this mb good or bad + string regionName = name; + if(name.Contains(".")) + { + if(string.IsNullOrWhiteSpace(m_ThisGatekeeper)) + return rinfo; // no HG + + string regionURI = ""; + if(!Util.buildHGRegionURI(name, out regionURI, out regionName) || string.IsNullOrWhiteSpace(regionName)) + return rinfo; // invalid + if(m_ThisGatekeeper != regionURI) + return rinfo; // not local grid + } + + List grinfo = m_RemoteGridService.GetRegionsByName(scopeID, regionName, maxNumber); if (grinfo != null) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index 25ae689..1378368 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -64,7 +64,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion"); config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion"); - m_LocalConnector = new LocalGridServicesConnector(config); + m_LocalConnector = new LocalGridServicesConnector(config, null); } /// @@ -88,7 +88,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests Scene s = new Scene(new RegionInfo()); s.RegionInfo.RegionID = r1.RegionID; m_LocalConnector.AddRegion(s); - + GridRegion r2 = new GridRegion(); r2.RegionName = "Test Region 2"; r2.RegionID = new UUID(2); @@ -198,4 +198,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected"); } } -} \ No newline at end of file +} -- cgit v1.1