From 132d701b3ea287c3ec0a9a4d9f852bb3b3a075f2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 20 Aug 2012 20:55:58 +0100 Subject: [PATCH] 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). --- OpenSim/Framework/Cache.cs | 83 ++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 79e20fc88e..31cab4a021 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -199,7 +199,14 @@ namespace OpenSim.Framework // public class Cache { + /// + /// Must only be accessed under lock. + /// private List m_Index = new List(); + + /// + /// Must only be accessed under m_Index lock. + /// private Dictionary m_Lookup = new Dictionary(); @@ -320,19 +327,19 @@ namespace OpenSim.Framework { if (m_Lookup.ContainsKey(index)) item = m_Lookup[index]; - } - if (item == null) - { + if (item == null) + { + Expire(true); + return null; + } + + item.hits++; + item.lastUsed = DateTime.Now; + Expire(true); - return null; } - item.hits++; - item.lastUsed = DateTime.Now; - - Expire(true); - return item; } @@ -385,7 +392,10 @@ namespace OpenSim.Framework // public Object Find(Predicate 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); } + /// + /// Expire items as appropriate. + /// + /// + /// Callers must lock m_Index. + /// + /// protected virtual void Expire(bool getting) { if (getting && (m_Strategy == CacheStrategy.Aggressive)) @@ -475,12 +493,10 @@ namespace OpenSim.Framework switch (m_Strategy) { - case CacheStrategy.Aggressive: - if (Count < Size) - return; + case CacheStrategy.Aggressive: + if (Count < Size) + return; - lock (m_Index) - { m_Index.Sort(new SortLRU()); m_Index.Reverse(); @@ -490,7 +506,7 @@ namespace OpenSim.Framework ExpireDelegate doExpire = OnExpire; - if (doExpire != null) + if (doExpire != null) { List candidates = m_Index.GetRange(target, Count - target); @@ -513,27 +529,34 @@ namespace OpenSim.Framework foreach (CacheItemBase item in m_Index) m_Lookup[item.uuid] = item; } - } - break; - default: - break; + + break; + + default: + break; } } public void Invalidate(string uuid) { - if (!m_Lookup.ContainsKey(uuid)) - return; + lock (m_Index) + { + if (!m_Lookup.ContainsKey(uuid)) + return; - CacheItemBase item = m_Lookup[uuid]; - m_Lookup.Remove(uuid); - m_Index.Remove(item); + CacheItemBase item = m_Lookup[uuid]; + m_Lookup.Remove(uuid); + m_Index.Remove(item); + } } public void Clear() { - m_Index.Clear(); - m_Lookup.Clear(); + lock (m_Index) + { + m_Index.Clear(); + m_Lookup.Clear(); + } } } -} +} \ No newline at end of file