Tighten up OpenSim.Framework.Cache locking to avoid race conditions.
This is to resolve a reported issue in http://opensimulator.org/mantis/view.php?id=6232 Here, the land management module is using OpenSim.Framework.Cache (the only code to currently do so apart from the non-default CoreAssetCache).integration
parent
bcbd450fe4
commit
970727e57e
|
@ -199,7 +199,14 @@ namespace OpenSim.Framework
|
||||||
//
|
//
|
||||||
public class Cache
|
public class Cache
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Must only be accessed under lock.
|
||||||
|
/// </summary>
|
||||||
private List<CacheItemBase> m_Index = new List<CacheItemBase>();
|
private List<CacheItemBase> m_Index = new List<CacheItemBase>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Must only be accessed under m_Index lock.
|
||||||
|
/// </summary>
|
||||||
private Dictionary<string, CacheItemBase> m_Lookup =
|
private Dictionary<string, CacheItemBase> m_Lookup =
|
||||||
new Dictionary<string, CacheItemBase>();
|
new Dictionary<string, CacheItemBase>();
|
||||||
|
|
||||||
|
@ -320,19 +327,19 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
if (m_Lookup.ContainsKey(index))
|
if (m_Lookup.ContainsKey(index))
|
||||||
item = m_Lookup[index];
|
item = m_Lookup[index];
|
||||||
}
|
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
|
Expire(true);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.hits++;
|
||||||
|
item.lastUsed = DateTime.Now;
|
||||||
|
|
||||||
Expire(true);
|
Expire(true);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item.hits++;
|
|
||||||
item.lastUsed = DateTime.Now;
|
|
||||||
|
|
||||||
Expire(true);
|
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +392,10 @@ namespace OpenSim.Framework
|
||||||
//
|
//
|
||||||
public Object Find(Predicate<CacheItemBase> d)
|
public Object Find(Predicate<CacheItemBase> d)
|
||||||
{
|
{
|
||||||
CacheItemBase item = m_Index.Find(d);
|
CacheItemBase item;
|
||||||
|
|
||||||
|
lock (m_Index)
|
||||||
|
item = m_Index.Find(d);
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -419,12 +429,12 @@ namespace OpenSim.Framework
|
||||||
public virtual void Store(string index, Object data, Type container,
|
public virtual void Store(string index, Object data, Type container,
|
||||||
Object[] parameters)
|
Object[] parameters)
|
||||||
{
|
{
|
||||||
Expire(false);
|
|
||||||
|
|
||||||
CacheItemBase item;
|
CacheItemBase item;
|
||||||
|
|
||||||
lock (m_Index)
|
lock (m_Index)
|
||||||
{
|
{
|
||||||
|
Expire(false);
|
||||||
|
|
||||||
if (m_Index.Contains(new CacheItemBase(index)))
|
if (m_Index.Contains(new CacheItemBase(index)))
|
||||||
{
|
{
|
||||||
if ((m_Flags & CacheFlags.AllowUpdate) != 0)
|
if ((m_Flags & CacheFlags.AllowUpdate) != 0)
|
||||||
|
@ -450,9 +460,17 @@ namespace OpenSim.Framework
|
||||||
m_Index.Add(item);
|
m_Index.Add(item);
|
||||||
m_Lookup[index] = item;
|
m_Lookup[index] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Store(data);
|
item.Store(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expire items as appropriate.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Callers must lock m_Index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name='getting'></param>
|
||||||
protected virtual void Expire(bool getting)
|
protected virtual void Expire(bool getting)
|
||||||
{
|
{
|
||||||
if (getting && (m_Strategy == CacheStrategy.Aggressive))
|
if (getting && (m_Strategy == CacheStrategy.Aggressive))
|
||||||
|
@ -475,12 +493,10 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
switch (m_Strategy)
|
switch (m_Strategy)
|
||||||
{
|
{
|
||||||
case CacheStrategy.Aggressive:
|
case CacheStrategy.Aggressive:
|
||||||
if (Count < Size)
|
if (Count < Size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (m_Index)
|
|
||||||
{
|
|
||||||
m_Index.Sort(new SortLRU());
|
m_Index.Sort(new SortLRU());
|
||||||
m_Index.Reverse();
|
m_Index.Reverse();
|
||||||
|
|
||||||
|
@ -490,7 +506,7 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
ExpireDelegate doExpire = OnExpire;
|
ExpireDelegate doExpire = OnExpire;
|
||||||
|
|
||||||
if (doExpire != null)
|
if (doExpire != null)
|
||||||
{
|
{
|
||||||
List<CacheItemBase> candidates =
|
List<CacheItemBase> candidates =
|
||||||
m_Index.GetRange(target, Count - target);
|
m_Index.GetRange(target, Count - target);
|
||||||
|
@ -513,27 +529,34 @@ namespace OpenSim.Framework
|
||||||
foreach (CacheItemBase item in m_Index)
|
foreach (CacheItemBase item in m_Index)
|
||||||
m_Lookup[item.uuid] = item;
|
m_Lookup[item.uuid] = item;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Invalidate(string uuid)
|
public void Invalidate(string uuid)
|
||||||
{
|
{
|
||||||
if (!m_Lookup.ContainsKey(uuid))
|
lock (m_Index)
|
||||||
return;
|
{
|
||||||
|
if (!m_Lookup.ContainsKey(uuid))
|
||||||
|
return;
|
||||||
|
|
||||||
CacheItemBase item = m_Lookup[uuid];
|
CacheItemBase item = m_Lookup[uuid];
|
||||||
m_Lookup.Remove(uuid);
|
m_Lookup.Remove(uuid);
|
||||||
m_Index.Remove(item);
|
m_Index.Remove(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
m_Index.Clear();
|
lock (m_Index)
|
||||||
m_Lookup.Clear();
|
{
|
||||||
|
m_Index.Clear();
|
||||||
|
m_Lookup.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue