From 970727e57e2fd478685b5853c855d3b471d5325d Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 20 Aug 2012 20:55:58 +0100
Subject: 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 79e20fc..31cab4a 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
--
cgit v1.1