diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs index 50433ba3ed..ca9b32716c 100644 --- a/OpenSim/Data/IRegionData.cs +++ b/OpenSim/Data/IRegionData.cs @@ -52,12 +52,12 @@ namespace OpenSim.Data public int sizeY; /// - /// Return the x-coordinate of this region. + /// Return the x-coordinate of this region in region units. /// public int coordX { get { return (int)Util.WorldToRegionLoc((uint)posX); } } /// - /// Return the y-coordinate of this region. + /// Return the y-coordinate of this region in region units. /// public int coordY { get { return (int)Util.WorldToRegionLoc((uint)posY); } } diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index 2836236fb7..013cc53866 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -46,7 +46,7 @@ namespace OpenSim.Services.GridService private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); -// private string LogHeader = "[GRID SERVICE]"; + private string LogHeader = "[GRID SERVICE]"; private bool m_DeleteOnUnregister = true; private static GridService m_RootInstance = null; @@ -57,6 +57,8 @@ namespace OpenSim.Services.GridService protected bool m_AllowDuplicateNames = false; protected bool m_AllowHypergridMapSearch = false; + protected bool m_SuppressVarregionOverlapCheckOnRegistration = false; + public GridService(IConfigSource config) : base(config) { @@ -81,6 +83,8 @@ namespace OpenSim.Services.GridService m_AllowDuplicateNames = gridConfig.GetBoolean("AllowDuplicateNames", m_AllowDuplicateNames); m_AllowHypergridMapSearch = gridConfig.GetBoolean("AllowHypergridMapSearch", m_AllowHypergridMapSearch); + m_SuppressVarregionOverlapCheckOnRegistration = gridConfig.GetBoolean("SuppressVarregionOverlapCheckOnRegistration", m_SuppressVarregionOverlapCheckOnRegistration); + // This service is also used locally by a simulator running in grid mode. This switches prevents // inappropriate console commands from being registered suppressConsoleCommands = gridConfig.GetBoolean("SuppressConsoleCommands", suppressConsoleCommands); @@ -148,12 +152,19 @@ namespace OpenSim.Services.GridService if (regionInfos.RegionID == UUID.Zero) return "Invalid RegionID - cannot be zero UUID"; - RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); - if ((region != null) && (region.RegionID != regionInfos.RegionID)) + String reason = "Region overlaps another region"; + RegionData region = FindAnyConflictingRegion(regionInfos, scopeID, out reason); + // If there is a conflicting region, if it has the same ID and same coordinates + // then it is a region re-registering (permissions and ownership checked later). + if ((region != null) + && ( (region.coordX != regionInfos.RegionCoordX) + || (region.coordY != regionInfos.RegionCoordY) + || (region.RegionID != regionInfos.RegionID) ) + ) { - m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.", - regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); - return "Region overlaps another region"; + // If not same ID and same coordinates, this new region has conflicts and can't be registered. + m_log.WarnFormat("{0} Register region conflict in scope {1}. {2}", LogHeader, scopeID, reason); + return reason; } if (region != null) @@ -283,6 +294,112 @@ namespace OpenSim.Services.GridService return String.Empty; } + /// + /// Search the region map for regions conflicting with this region. + /// The region to be added is passed and we look for any existing regions that are + /// in the requested location, that are large varregions that overlap this region, or + /// are previously defined regions that would lie under this new region. + /// + /// Information on region requested to be added to the world map + /// Grid id for region + /// The reason the returned region conflicts with passed region + /// + private RegionData FindAnyConflictingRegion(GridRegion regionInfos, UUID scopeID, out string reason) + { + reason = "Reregistration"; + // First see if there is an existing region right where this region is trying to go + // (We keep this result so it can be returned if suppressing errors) + RegionData noErrorRegion = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); + RegionData region = noErrorRegion; + if (region != null + && region.RegionID == regionInfos.RegionID + && region.sizeX == regionInfos.RegionSizeX + && region.sizeY == regionInfos.RegionSizeY) + { + // If this seems to be exactly the same region, return this as it could be + // a re-registration (permissions checked by calling routine). + m_log.DebugFormat("{0} FindAnyConflictingRegion: re-register of {1}", + LogHeader, RegionString(regionInfos)); + return region; + } + + // No region exactly there or we're resizing an existing region. + // Fetch regions that could be varregions overlapping requested location. + int xmin = regionInfos.RegionLocX - (int)Constants.MaximumRegionSize + 10; + int xmax = regionInfos.RegionLocX; + int ymin = regionInfos.RegionLocY - (int)Constants.MaximumRegionSize + 10; + int ymax = regionInfos.RegionLocY; + List rdatas = m_Database.Get(xmin, ymin, xmax, ymax, scopeID); + foreach (RegionData rdata in rdatas) + { + // m_log.DebugFormat("{0} FindAnyConflictingRegion: find existing. Checking {1}", LogHeader, RegionString(rdata) ); + if ( (rdata.posX + rdata.sizeX > regionInfos.RegionLocX) + && (rdata.posY + rdata.sizeY > regionInfos.RegionLocY) ) + { + region = rdata; + m_log.WarnFormat("{0} FindAnyConflictingRegion: conflict of {1} by existing varregion {2}", + LogHeader, RegionString(regionInfos), RegionString(region)); + reason = String.Format("Region location is overlapped by existing varregion {0}", + RegionString(region)); + + if (m_SuppressVarregionOverlapCheckOnRegistration) + region = noErrorRegion; + return region; + } + } + + // There isn't a region that overlaps this potential region. + // See if this potential region overlaps an existing region. + // First, a shortcut of not looking for overlap if new region is legacy region sized + // and connot overlap anything. + if (regionInfos.RegionSizeX != Constants.RegionSize + || regionInfos.RegionSizeY != Constants.RegionSize) + { + // trim range looked for so we don't pick up neighbor regions just off the edges + xmin = regionInfos.RegionLocX; + xmax = regionInfos.RegionLocX + regionInfos.RegionSizeX - 10; + ymin = regionInfos.RegionLocY; + ymax = regionInfos.RegionLocY + regionInfos.RegionSizeY - 10; + rdatas = m_Database.Get(xmin, ymin, xmax, ymax, scopeID); + + // If the region is being resized, the found region could be ourself. + foreach (RegionData rdata in rdatas) + { + // m_log.DebugFormat("{0} FindAnyConflictingRegion: see if overlap. Checking {1}", LogHeader, RegionString(rdata) ); + if (region == null || region.RegionID != regionInfos.RegionID) + { + region = rdata; + m_log.WarnFormat("{0} FindAnyConflictingRegion: conflict of varregion {1} overlaps existing region {2}", + LogHeader, RegionString(regionInfos), RegionString(region)); + reason = String.Format("Region {0} would overlap existing region {1}", + RegionString(regionInfos), RegionString(region)); + + if (m_SuppressVarregionOverlapCheckOnRegistration) + region = noErrorRegion; + return region; + } + } + } + + // If we get here, region is either null (nothing found here) or + // is the non-conflicting region found at the location being requested. + return region; + } + + // String describing name and region location of passed region + private String RegionString(RegionData reg) + { + return String.Format("{0}/{1} at <{2},{3}>", + reg.RegionName, reg.RegionID, reg.coordX, reg.coordY); + } + + // String describing name and region location of passed region + private String RegionString(GridRegion reg) + { + return String.Format("{0}/{1} at <{2},{3}>", + reg.RegionName, reg.RegionID, reg.RegionCoordX, reg.RegionCoordY); + } + public bool DeregisterRegion(UUID regionID) { RegionData region = m_Database.Get(regionID, UUID.Zero); diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index dec3d35e08..b7bcd6bd51 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -186,12 +186,12 @@ namespace OpenSim.Services.Interfaces protected IPEndPoint m_internalEndPoint; /// - /// The co-ordinate of this region. + /// The co-ordinate of this region in region units. /// public int RegionCoordX { get { return (int)Util.WorldToRegionLoc((uint)RegionLocX); } } /// - /// The co-ordinate of this region + /// The co-ordinate of this region in region units /// public int RegionCoordY { get { return (int)Util.WorldToRegionLoc((uint)RegionLocY); } }