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).
0.7.4.1
Justin Clark-Casey (justincc) 2012-08-20 20:55:58 +01:00
parent 3b97241716
commit 132d701b3e
1 changed files with 53 additions and 30 deletions

View File

@ -199,7 +199,14 @@ namespace OpenSim.Framework
//
public class Cache
{
/// <summary>
/// Must only be accessed under lock.
/// </summary>
private List<CacheItemBase> m_Index = new List<CacheItemBase>();
/// <summary>
/// Must only be accessed under m_Index lock.
/// </summary>
private Dictionary<string, CacheItemBase> m_Lookup =
new Dictionary<string, CacheItemBase>();
@ -320,7 +327,6 @@ namespace OpenSim.Framework
{
if (m_Lookup.ContainsKey(index))
item = m_Lookup[index];
}
if (item == null)
{
@ -332,6 +338,7 @@ namespace OpenSim.Framework
item.lastUsed = DateTime.Now;
Expire(true);
}
return item;
}
@ -385,7 +392,10 @@ namespace OpenSim.Framework
//
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)
return null;
@ -419,12 +429,12 @@ namespace OpenSim.Framework
public virtual void Store(string index, Object data, Type container,
Object[] parameters)
{
Expire(false);
CacheItemBase item;
lock (m_Index)
{
Expire(false);
if (m_Index.Contains(new CacheItemBase(index)))
{
if ((m_Flags & CacheFlags.AllowUpdate) != 0)
@ -450,9 +460,17 @@ namespace OpenSim.Framework
m_Index.Add(item);
m_Lookup[index] = item;
}
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)
{
if (getting && (m_Strategy == CacheStrategy.Aggressive))
@ -479,8 +497,6 @@ namespace OpenSim.Framework
if (Count < Size)
return;
lock (m_Index)
{
m_Index.Sort(new SortLRU());
m_Index.Reverse();
@ -513,14 +529,17 @@ namespace OpenSim.Framework
foreach (CacheItemBase item in m_Index)
m_Lookup[item.uuid] = item;
}
}
break;
default:
break;
}
}
public void Invalidate(string uuid)
{
lock (m_Index)
{
if (!m_Lookup.ContainsKey(uuid))
return;
@ -529,11 +548,15 @@ namespace OpenSim.Framework
m_Lookup.Remove(uuid);
m_Index.Remove(item);
}
}
public void Clear()
{
lock (m_Index)
{
m_Index.Clear();
m_Lookup.Clear();
}
}
}
}