fix RegionInfoCache keys compare, remove RegionCache now replaced by RegionInfoCache

LSLKeyTest
UbitUmarov 2016-07-30 17:14:17 +01:00
parent 79b7787eff
commit bf593dd6f4
3 changed files with 70 additions and 134 deletions

View File

@ -51,7 +51,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]";
private IGridService m_GridService;
private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>();
private RegionInfoCache m_RegionInfoCache = null;
private bool m_Enabled;
@ -151,13 +150,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
scene.RegisterModuleInterface<IGridService>(this);
lock (m_LocalCache)
{
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));
}
m_RegionInfoCache.CacheLocal(new GridRegion(scene.RegionInfo));
scene.EventManager.OnRegionUp += OnRegionUp;
}
public void RemoveRegion(Scene scene)
@ -165,11 +159,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
if (!m_Enabled)
return;
lock (m_LocalCache)
{
m_LocalCache[scene.RegionInfo.RegionID].Clear();
m_LocalCache.Remove(scene.RegionInfo.RegionID);
}
m_RegionInfoCache.Remove(scene.RegionInfo.ScopeID, scene.RegionInfo.RegionID);
scene.EventManager.OnRegionUp -= OnRegionUp;
}
public void RegionLoaded(Scene scene)
@ -180,6 +171,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);
@ -291,7 +291,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
public void HandleShowNeighboursCommand(string module, string[] cmdparams)
{
System.Text.StringBuilder caps = new System.Text.StringBuilder();
/* temporary broken
lock (m_LocalCache)
{
foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
@ -304,6 +304,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
}
MainConsole.Instance.Output(caps.ToString());
*/
MainConsole.Instance.Output("Neighbours list not avaiable in this version\n");
}
}
}

View File

@ -1,103 +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<ulong, GridRegion> m_neighbours = new Dictionary<ulong, GridRegion>();
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<GridRegion> GetNeighbours()
{
return new List<GridRegion>(m_neighbours.Values);
}
public GridRegion GetRegionByPosition(int x, int y)
{
// do actual search by position
// not the best, but this will not hold that many regions
GridRegion foundRegion = null;
foreach(GridRegion r in m_neighbours.Values)
{
if (x >= r.RegionLocX && x < r.RegionLocX + r.RegionSizeX
&& y >= r.RegionLocY && y < r.RegionLocY + r.RegionSizeY)
{
foundRegion = r;
break;
}
}
return foundRegion;
}
}
}

View File

@ -59,26 +59,42 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
public void Cache(UUID scopeID, GridRegion rinfo)
{
// 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;
m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
}
public void CacheLocal(GridRegion rinfo)
{
if (rinfo == null)
return;
m_Cache.AddOrUpdate(rinfo.ScopeID, rinfo, 1e7f);
}
public void CacheNearNeighbour(UUID scopeID, GridRegion rinfo)
{
if (rinfo == null)
return;
// m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
m_Cache.Add(scopeID, rinfo, CACHE_EXPIRATION_SECONDS); // don't override local regions
}
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;
m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds);
}
public void Remove(UUID scopeID, UUID regionID)
{
m_Cache.Remove(scopeID, regionID);
}
public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
{
inCache = false;
@ -134,15 +150,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return null;
}
}
// following code partialy adapted from lib OpenMetaverse
public class RegionKey : IComparable<RegionKey>
public class RegionKey
{
private UUID m_scopeID;
private UUID m_RegionID;
public UUID m_scopeID;
public UUID m_RegionID;
private DateTime m_expirationDate;
public RegionKey(UUID scopeID, UUID id)
@ -161,16 +176,34 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
set { m_expirationDate = value; }
}
public int GetHaskCode()
public override int GetHashCode()
{
int hash = m_scopeID.GetHashCode();
hash += hash * 23 + m_RegionID.GetHashCode();
return hash;
}
public int CompareTo(RegionKey other)
public override bool Equals(Object b)
{
return GetHashCode().CompareTo(other.GetHashCode());
if(b == null)
return false;
RegionKey kb = b as RegionKey;
return (m_scopeID == kb.m_scopeID && m_RegionID == kb.m_RegionID);
}
}
class RegionKeyEqual : EqualityComparer<RegionKey>
{
public override int GetHashCode(RegionKey rk)
{
int hash = rk.m_scopeID.GetHashCode();
hash += hash * 23 + rk.m_RegionID.GetHashCode();
return hash;
}
public override bool Equals(RegionKey a, RegionKey b)
{
return (a.m_scopeID == b.m_scopeID && a.m_RegionID == b.m_RegionID);
}
}
@ -246,7 +279,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
}
}
public sealed class RegionsExpiringCache
public class RegionsExpiringCache
{
const double CACHE_PURGE_HZ = 60; // seconds
const int MAX_LOCK_WAIT = 10000; // milliseconds
@ -256,7 +289,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
/// <summary>For thread safety</summary>
object isPurging = new object();
Dictionary<RegionKey, GridRegion> timedStorage = new Dictionary<RegionKey, GridRegion>();
static RegionKeyEqual keyequal = new RegionKeyEqual();
Dictionary<RegionKey, GridRegion> timedStorage = new Dictionary<RegionKey, GridRegion>(keyequal);
Dictionary<UUID, RegionInfoByScope> InfobyScope = new Dictionary<UUID, RegionInfoByScope>();
private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds);
@ -370,10 +404,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return timedStorage.Count;
}
}
public bool Remove(UUID scope, GridRegion region)
{
RegionKey key = new RegionKey(scope, region.RegionID);
return Remove(scope, region.RegionID);
}
public bool Remove(UUID scope, UUID regionID)
{
RegionKey key = new RegionKey(scope, regionID);
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");