From c4eac71e54544fb3dbf7283969a6e229225d9621 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 7 Aug 2008 16:40:50 +0000 Subject: Committing first draft of the universal cache. This is by no means finished, but it does work for memory caching items in aggressive mode. Supports several paramters, including TTL. --- OpenSim/Framework/Cache.cs | 467 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 467 insertions(+) create mode 100644 OpenSim/Framework/Cache.cs (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs new file mode 100644 index 0000000..88b86a3 --- /dev/null +++ b/OpenSim/Framework/Cache.cs @@ -0,0 +1,467 @@ +using System; +using System.Collections.Generic; +using libsecondlife; + +namespace Opensim.Framework +{ + // The delegate we will use for performing fetch from backing store + // + public delegate Object FetchDelegate(LLUUID index); + public delegate bool ExpireDelegate(LLUUID index); + + // Strategy + // + // Conservative = Minimize memory. Expire items quickly. + // Balanced = Expire items with few hits quickly. + // Aggressive = Keep cache full. Expire only when over 90% and adding + // + public enum CacheStrategy + { + Conservative = 0, + Balanced = 1, + Aggressive = 2 + } + + // Select classes to store data on different media + // + public enum CacheMedium + { + Memory = 0, + File = 1 + } + + public enum CacheFlags + { + CacheMissing = 1, + AllowUpdate = 2 + } + + // The base class of all cache objects. Implements comparison and sorting + // by the LLUUID member. + // + // This is not abstract because we need to instantiate it briefly as a + // method parameter + // + public class CacheItemBase : IEquatable, IComparable + { + public LLUUID uuid; + public DateTime entered; + public DateTime lastUsed; + public DateTime expires = new DateTime(0); + public int hits = 0; + + public virtual Object Retrieve() + { + return null; + } + + public virtual void Store(Object data) + { + } + + public CacheItemBase(LLUUID index) + { + uuid = index; + entered = DateTime.Now; + lastUsed = entered; + } + + public CacheItemBase(LLUUID index, DateTime ttl) + { + uuid = index; + entered = DateTime.Now; + lastUsed = entered; + expires = ttl; + } + + public virtual bool Equals(CacheItemBase item) + { + return uuid == item.uuid; + } + + public virtual int CompareTo(CacheItemBase item) + { + return uuid.CompareTo(item.uuid); + } + + public virtual bool IsLocked() + { + return false; + } + } + + // Simple in-memory storage. Boxes the object and stores it in a variable + // + public class MemoryCacheItem : CacheItemBase + { + private Object m_Data; + + public MemoryCacheItem(LLUUID index) : + base(index) + { + } + + public MemoryCacheItem(LLUUID index, DateTime ttl) : + base(index, ttl) + { + } + + public MemoryCacheItem(LLUUID index, Object data) : + base(index) + { + Store(data); + } + + public MemoryCacheItem(LLUUID index, DateTime ttl, Object data) : + base(index, ttl) + { + Store(data); + } + + public override Object Retrieve() + { + return m_Data; + } + + public override void Store(Object data) + { + m_Data = data; + } + } + + // Simple persistent file storage + // + public class FileCacheItem : CacheItemBase + { + public FileCacheItem(LLUUID index) : + base(index) + { + } + + public FileCacheItem(LLUUID index, DateTime ttl) : + base(index, ttl) + { + } + + public FileCacheItem(LLUUID index, Object data) : + base(index) + { + Store(data); + } + + public FileCacheItem(LLUUID index, DateTime ttl, Object data) : + base(index, ttl) + { + Store(data); + } + + public override Object Retrieve() + { + //TODO: Add file access code + return null; + } + + public override void Store(Object data) + { + //TODO: Add file access code + } + } + + // The main cache class. This is the class you instantiate to create + // a cache + // + public class Cache + { + private List m_Index = new List(); + + private CacheStrategy m_Strategy; + private CacheMedium m_Medium; + private CacheFlags m_Flags = 0; + private int m_Size = 1024; + private TimeSpan m_DefaultTTL = new TimeSpan(0); + public ExpireDelegate OnExpire; + + // Comparison interfaces + // + private class SortLRU : IComparer + { + public int Compare(CacheItemBase a, CacheItemBase b) + { + if(a == null && b == null) + return 0; + if(a == null) + return -1; + if(b == null) + return 1; + + return(a.lastUsed.CompareTo(b.lastUsed)); + } + } + + // Convenience constructors + // + public Cache() + { + m_Strategy = CacheStrategy.Balanced; + m_Medium = CacheMedium.Memory; + m_Flags = 0; + } + + public Cache(CacheMedium medium) : + this(medium, CacheStrategy.Balanced) + { + } + + public Cache(CacheMedium medium, CacheFlags flags) : + this(medium, CacheStrategy.Balanced, flags) + { + } + + public Cache(CacheMedium medium, CacheStrategy strategy) : + this(medium, strategy, 0) + { + } + + public Cache(CacheStrategy strategy, CacheFlags flags) : + this(CacheMedium.Memory, strategy, flags) + { + } + + public Cache(CacheFlags flags) : + this(CacheMedium.Memory, CacheStrategy.Balanced, flags) + { + } + + public Cache(CacheMedium medium, CacheStrategy strategy, + CacheFlags flags) + { + m_Strategy = strategy; + m_Medium = medium; + m_Flags = flags; + } + + // Count of the items currently in cache + // + public int Count + { + get { lock(m_Index) { return m_Index.Count; } } + } + + // Maximum number of items this cache will hold + // + public int Size + { + get { return m_Size; } + set { SetSize(value); } + } + + private void SetSize(int newSize) + { + lock(m_Index) + { + if(Count <= Size) + return; + + m_Index.Sort(new SortLRU()); + m_Index.Reverse(); + + m_Index.RemoveRange(newSize, Count - newSize); + m_Size = newSize; + } + } + + public TimeSpan DefaultTTL + { + get { return m_DefaultTTL; } + set { m_DefaultTTL = value; } + } + + // Get an item from cache. Return the raw item, not it's data + // + protected virtual CacheItemBase GetItem(LLUUID index) + { + CacheItemBase item = null; + + lock(m_Index) + { + item = m_Index.Find(delegate(CacheItemBase i) + { + if(i.uuid == index) + return true; + return false; + }); + } + + if(item == null) + { + Expire(true); + return null; + } + + item.hits++; + item.lastUsed = DateTime.Now; + + Expire(true); + + return item; + } + + // Get an item from cache. Do not try to fetch from source if not + // present. Just return null + // + public virtual Object Get(LLUUID index) + { + CacheItemBase item = GetItem(index); + + if(item == null) + return null; + + return item.Retrieve(); + } + + // Fetch an object from backing store if not cached, serve from + // cache if it is. + // + public virtual Object Get(LLUUID index, FetchDelegate fetch) + { + Object item = Get(index); + if(item != null) + return item; + + Object data = fetch(index); + if(data == null) + { + if((m_Flags & CacheFlags.CacheMissing) != 0) + { + lock(m_Index) + { + CacheItemBase missing = new CacheItemBase(index); + if(!m_Index.Contains(missing)) + m_Index.Add(missing); + } + } + return null; + } + + Store(index, data); + + return data; + } + + + public virtual void Store(LLUUID index, Object data) + { + Type container; + + switch(m_Medium) + { + case CacheMedium.Memory: + container = typeof(MemoryCacheItem); + break; + case CacheMedium.File: + return; + default: + return; + } + + Store(index, data, container); + } + + public virtual void Store(LLUUID index, Object data, Type container) + { + Store(index, data, container, new Object[] { index }); + } + + public virtual void Store(LLUUID index, Object data, Type container, + Object[] parameters) + { + Expire(false); + + CacheItemBase item; + + lock(m_Index) + { + if(m_Index.Contains(new CacheItemBase(index))) + { + if((m_Flags & CacheFlags.AllowUpdate) != 0) + { + item = GetItem(index); + + item.hits++; + item.lastUsed = DateTime.Now; + if(m_DefaultTTL.Ticks != 0) + item.expires = DateTime.Now + m_DefaultTTL; + + item.Store(data); + } + return; + } + + item = (CacheItemBase)Activator.CreateInstance(container, + parameters); + + if(m_DefaultTTL.Ticks != 0) + item.expires = DateTime.Now + m_DefaultTTL; + + m_Index.Add(item); + } + item.Store(data); + } + + protected virtual void Expire(bool getting) + { + if(getting && (m_Strategy == CacheStrategy.Aggressive)) + return; + + if(m_DefaultTTL.Ticks != 0) + { + DateTime now= System.DateTime.Now; + + foreach (CacheItemBase item in new List(m_Index)) + { + if(item.expires.Ticks == 0 || + item.expires <= now) + m_Index.Remove(item); + } + } + + switch (m_Strategy) + { + case CacheStrategy.Aggressive: + if(Count < Size) + return; + + lock(m_Index) + { + m_Index.Sort(new SortLRU()); + m_Index.Reverse(); + + int target = (int)((float)Size * 0.9); + if(target == Count) // Cover ridiculous cache sizes + return; + + ExpireDelegate doExpire = OnExpire; + + if(doExpire != null) + { + List candidates = + m_Index.GetRange(target, Count - target); + + foreach (CacheItemBase i in candidates) + { + if(doExpire(i.uuid)) + m_Index.Remove(i); + } + } + else + { + m_Index.RemoveRange(target, Count - target); + } + } + break; + default: + break; + } + } + } +} -- cgit v1.1 From 657af5e61108b9acc6f9097362e5ebeea7d69a92 Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Fri, 8 Aug 2008 06:39:35 +0000 Subject: Update svn properties, minor formatting cleanup. --- OpenSim/Framework/Cache.cs | 920 ++++++++++++++++++++++----------------------- 1 file changed, 460 insertions(+), 460 deletions(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 88b86a3..780e262 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -4,464 +4,464 @@ using libsecondlife; namespace Opensim.Framework { - // The delegate we will use for performing fetch from backing store - // - public delegate Object FetchDelegate(LLUUID index); - public delegate bool ExpireDelegate(LLUUID index); - - // Strategy - // - // Conservative = Minimize memory. Expire items quickly. - // Balanced = Expire items with few hits quickly. - // Aggressive = Keep cache full. Expire only when over 90% and adding - // - public enum CacheStrategy - { - Conservative = 0, - Balanced = 1, - Aggressive = 2 - } - - // Select classes to store data on different media - // - public enum CacheMedium - { - Memory = 0, - File = 1 - } - - public enum CacheFlags - { - CacheMissing = 1, - AllowUpdate = 2 - } - - // The base class of all cache objects. Implements comparison and sorting - // by the LLUUID member. - // - // This is not abstract because we need to instantiate it briefly as a - // method parameter - // - public class CacheItemBase : IEquatable, IComparable - { - public LLUUID uuid; - public DateTime entered; - public DateTime lastUsed; - public DateTime expires = new DateTime(0); - public int hits = 0; - - public virtual Object Retrieve() - { - return null; - } - - public virtual void Store(Object data) - { - } - - public CacheItemBase(LLUUID index) - { - uuid = index; - entered = DateTime.Now; - lastUsed = entered; - } - - public CacheItemBase(LLUUID index, DateTime ttl) - { - uuid = index; - entered = DateTime.Now; - lastUsed = entered; - expires = ttl; - } - - public virtual bool Equals(CacheItemBase item) - { - return uuid == item.uuid; - } - - public virtual int CompareTo(CacheItemBase item) - { - return uuid.CompareTo(item.uuid); - } - - public virtual bool IsLocked() - { - return false; - } - } - - // Simple in-memory storage. Boxes the object and stores it in a variable - // - public class MemoryCacheItem : CacheItemBase - { - private Object m_Data; - - public MemoryCacheItem(LLUUID index) : - base(index) - { - } - - public MemoryCacheItem(LLUUID index, DateTime ttl) : - base(index, ttl) - { - } - - public MemoryCacheItem(LLUUID index, Object data) : - base(index) - { - Store(data); - } - - public MemoryCacheItem(LLUUID index, DateTime ttl, Object data) : - base(index, ttl) - { - Store(data); - } - - public override Object Retrieve() - { - return m_Data; - } - - public override void Store(Object data) - { - m_Data = data; - } - } - - // Simple persistent file storage - // - public class FileCacheItem : CacheItemBase - { - public FileCacheItem(LLUUID index) : - base(index) - { - } - - public FileCacheItem(LLUUID index, DateTime ttl) : - base(index, ttl) - { - } - - public FileCacheItem(LLUUID index, Object data) : - base(index) - { - Store(data); - } - - public FileCacheItem(LLUUID index, DateTime ttl, Object data) : - base(index, ttl) - { - Store(data); - } - - public override Object Retrieve() - { - //TODO: Add file access code - return null; - } - - public override void Store(Object data) - { - //TODO: Add file access code - } - } - - // The main cache class. This is the class you instantiate to create - // a cache - // - public class Cache - { - private List m_Index = new List(); - - private CacheStrategy m_Strategy; - private CacheMedium m_Medium; - private CacheFlags m_Flags = 0; - private int m_Size = 1024; - private TimeSpan m_DefaultTTL = new TimeSpan(0); - public ExpireDelegate OnExpire; - - // Comparison interfaces - // - private class SortLRU : IComparer - { - public int Compare(CacheItemBase a, CacheItemBase b) - { - if(a == null && b == null) - return 0; - if(a == null) - return -1; - if(b == null) - return 1; - - return(a.lastUsed.CompareTo(b.lastUsed)); - } - } - - // Convenience constructors - // - public Cache() - { - m_Strategy = CacheStrategy.Balanced; - m_Medium = CacheMedium.Memory; - m_Flags = 0; - } - - public Cache(CacheMedium medium) : - this(medium, CacheStrategy.Balanced) - { - } - - public Cache(CacheMedium medium, CacheFlags flags) : - this(medium, CacheStrategy.Balanced, flags) - { - } - - public Cache(CacheMedium medium, CacheStrategy strategy) : - this(medium, strategy, 0) - { - } - - public Cache(CacheStrategy strategy, CacheFlags flags) : - this(CacheMedium.Memory, strategy, flags) - { - } - - public Cache(CacheFlags flags) : - this(CacheMedium.Memory, CacheStrategy.Balanced, flags) - { - } - - public Cache(CacheMedium medium, CacheStrategy strategy, - CacheFlags flags) - { - m_Strategy = strategy; - m_Medium = medium; - m_Flags = flags; - } - - // Count of the items currently in cache - // - public int Count - { - get { lock(m_Index) { return m_Index.Count; } } - } - - // Maximum number of items this cache will hold - // - public int Size - { - get { return m_Size; } - set { SetSize(value); } - } - - private void SetSize(int newSize) - { - lock(m_Index) - { - if(Count <= Size) - return; - - m_Index.Sort(new SortLRU()); - m_Index.Reverse(); - - m_Index.RemoveRange(newSize, Count - newSize); - m_Size = newSize; - } - } - - public TimeSpan DefaultTTL - { - get { return m_DefaultTTL; } - set { m_DefaultTTL = value; } - } - - // Get an item from cache. Return the raw item, not it's data - // - protected virtual CacheItemBase GetItem(LLUUID index) - { - CacheItemBase item = null; - - lock(m_Index) - { - item = m_Index.Find(delegate(CacheItemBase i) - { - if(i.uuid == index) - return true; - return false; - }); - } - - if(item == null) - { - Expire(true); - return null; - } - - item.hits++; - item.lastUsed = DateTime.Now; - - Expire(true); - - return item; - } - - // Get an item from cache. Do not try to fetch from source if not - // present. Just return null - // - public virtual Object Get(LLUUID index) - { - CacheItemBase item = GetItem(index); - - if(item == null) - return null; - - return item.Retrieve(); - } - - // Fetch an object from backing store if not cached, serve from - // cache if it is. - // - public virtual Object Get(LLUUID index, FetchDelegate fetch) - { - Object item = Get(index); - if(item != null) - return item; - - Object data = fetch(index); - if(data == null) - { - if((m_Flags & CacheFlags.CacheMissing) != 0) - { - lock(m_Index) - { - CacheItemBase missing = new CacheItemBase(index); - if(!m_Index.Contains(missing)) - m_Index.Add(missing); - } - } - return null; - } - - Store(index, data); - - return data; - } - - - public virtual void Store(LLUUID index, Object data) - { - Type container; - - switch(m_Medium) - { - case CacheMedium.Memory: - container = typeof(MemoryCacheItem); - break; - case CacheMedium.File: - return; - default: - return; - } - - Store(index, data, container); - } - - public virtual void Store(LLUUID index, Object data, Type container) - { - Store(index, data, container, new Object[] { index }); - } - - public virtual void Store(LLUUID index, Object data, Type container, - Object[] parameters) - { - Expire(false); - - CacheItemBase item; - - lock(m_Index) - { - if(m_Index.Contains(new CacheItemBase(index))) - { - if((m_Flags & CacheFlags.AllowUpdate) != 0) - { - item = GetItem(index); - - item.hits++; - item.lastUsed = DateTime.Now; - if(m_DefaultTTL.Ticks != 0) - item.expires = DateTime.Now + m_DefaultTTL; - - item.Store(data); - } - return; - } - - item = (CacheItemBase)Activator.CreateInstance(container, - parameters); - - if(m_DefaultTTL.Ticks != 0) - item.expires = DateTime.Now + m_DefaultTTL; - - m_Index.Add(item); - } - item.Store(data); - } - - protected virtual void Expire(bool getting) - { - if(getting && (m_Strategy == CacheStrategy.Aggressive)) - return; - - if(m_DefaultTTL.Ticks != 0) - { - DateTime now= System.DateTime.Now; - - foreach (CacheItemBase item in new List(m_Index)) - { - if(item.expires.Ticks == 0 || - item.expires <= now) - m_Index.Remove(item); - } - } - - switch (m_Strategy) - { - case CacheStrategy.Aggressive: - if(Count < Size) - return; - - lock(m_Index) - { - m_Index.Sort(new SortLRU()); - m_Index.Reverse(); - - int target = (int)((float)Size * 0.9); - if(target == Count) // Cover ridiculous cache sizes - return; - - ExpireDelegate doExpire = OnExpire; - - if(doExpire != null) - { - List candidates = - m_Index.GetRange(target, Count - target); - - foreach (CacheItemBase i in candidates) - { - if(doExpire(i.uuid)) - m_Index.Remove(i); - } - } - else - { - m_Index.RemoveRange(target, Count - target); - } - } - break; - default: - break; - } - } - } + // The delegate we will use for performing fetch from backing store + // + public delegate Object FetchDelegate(LLUUID index); + public delegate bool ExpireDelegate(LLUUID index); + + // Strategy + // + // Conservative = Minimize memory. Expire items quickly. + // Balanced = Expire items with few hits quickly. + // Aggressive = Keep cache full. Expire only when over 90% and adding + // + public enum CacheStrategy + { + Conservative = 0, + Balanced = 1, + Aggressive = 2 + } + + // Select classes to store data on different media + // + public enum CacheMedium + { + Memory = 0, + File = 1 + } + + public enum CacheFlags + { + CacheMissing = 1, + AllowUpdate = 2 + } + + // The base class of all cache objects. Implements comparison and sorting + // by the LLUUID member. + // + // This is not abstract because we need to instantiate it briefly as a + // method parameter + // + public class CacheItemBase : IEquatable, IComparable + { + public LLUUID uuid; + public DateTime entered; + public DateTime lastUsed; + public DateTime expires = new DateTime(0); + public int hits = 0; + + public virtual Object Retrieve() + { + return null; + } + + public virtual void Store(Object data) + { + } + + public CacheItemBase(LLUUID index) + { + uuid = index; + entered = DateTime.Now; + lastUsed = entered; + } + + public CacheItemBase(LLUUID index, DateTime ttl) + { + uuid = index; + entered = DateTime.Now; + lastUsed = entered; + expires = ttl; + } + + public virtual bool Equals(CacheItemBase item) + { + return uuid == item.uuid; + } + + public virtual int CompareTo(CacheItemBase item) + { + return uuid.CompareTo(item.uuid); + } + + public virtual bool IsLocked() + { + return false; + } + } + + // Simple in-memory storage. Boxes the object and stores it in a variable + // + public class MemoryCacheItem : CacheItemBase + { + private Object m_Data; + + public MemoryCacheItem(LLUUID index) : + base(index) + { + } + + public MemoryCacheItem(LLUUID index, DateTime ttl) : + base(index, ttl) + { + } + + public MemoryCacheItem(LLUUID index, Object data) : + base(index) + { + Store(data); + } + + public MemoryCacheItem(LLUUID index, DateTime ttl, Object data) : + base(index, ttl) + { + Store(data); + } + + public override Object Retrieve() + { + return m_Data; + } + + public override void Store(Object data) + { + m_Data = data; + } + } + + // Simple persistent file storage + // + public class FileCacheItem : CacheItemBase + { + public FileCacheItem(LLUUID index) : + base(index) + { + } + + public FileCacheItem(LLUUID index, DateTime ttl) : + base(index, ttl) + { + } + + public FileCacheItem(LLUUID index, Object data) : + base(index) + { + Store(data); + } + + public FileCacheItem(LLUUID index, DateTime ttl, Object data) : + base(index, ttl) + { + Store(data); + } + + public override Object Retrieve() + { + //TODO: Add file access code + return null; + } + + public override void Store(Object data) + { + //TODO: Add file access code + } + } + + // The main cache class. This is the class you instantiate to create + // a cache + // + public class Cache + { + private List m_Index = new List(); + + private CacheStrategy m_Strategy; + private CacheMedium m_Medium; + private CacheFlags m_Flags = 0; + private int m_Size = 1024; + private TimeSpan m_DefaultTTL = new TimeSpan(0); + public ExpireDelegate OnExpire; + + // Comparison interfaces + // + private class SortLRU : IComparer + { + public int Compare(CacheItemBase a, CacheItemBase b) + { + if (a == null && b == null) + return 0; + if (a == null) + return -1; + if (b == null) + return 1; + + return(a.lastUsed.CompareTo(b.lastUsed)); + } + } + + // Convenience constructors + // + public Cache() + { + m_Strategy = CacheStrategy.Balanced; + m_Medium = CacheMedium.Memory; + m_Flags = 0; + } + + public Cache(CacheMedium medium) : + this(medium, CacheStrategy.Balanced) + { + } + + public Cache(CacheMedium medium, CacheFlags flags) : + this(medium, CacheStrategy.Balanced, flags) + { + } + + public Cache(CacheMedium medium, CacheStrategy strategy) : + this(medium, strategy, 0) + { + } + + public Cache(CacheStrategy strategy, CacheFlags flags) : + this(CacheMedium.Memory, strategy, flags) + { + } + + public Cache(CacheFlags flags) : + this(CacheMedium.Memory, CacheStrategy.Balanced, flags) + { + } + + public Cache(CacheMedium medium, CacheStrategy strategy, + CacheFlags flags) + { + m_Strategy = strategy; + m_Medium = medium; + m_Flags = flags; + } + + // Count of the items currently in cache + // + public int Count + { + get { lock (m_Index) { return m_Index.Count; } } + } + + // Maximum number of items this cache will hold + // + public int Size + { + get { return m_Size; } + set { SetSize(value); } + } + + private void SetSize(int newSize) + { + lock (m_Index) + { + if (Count <= Size) + return; + + m_Index.Sort(new SortLRU()); + m_Index.Reverse(); + + m_Index.RemoveRange(newSize, Count - newSize); + m_Size = newSize; + } + } + + public TimeSpan DefaultTTL + { + get { return m_DefaultTTL; } + set { m_DefaultTTL = value; } + } + + // Get an item from cache. Return the raw item, not it's data + // + protected virtual CacheItemBase GetItem(LLUUID index) + { + CacheItemBase item = null; + + lock (m_Index) + { + item = m_Index.Find(delegate(CacheItemBase i) + { + if (i.uuid == index) + return true; + return false; + }); + } + + if (item == null) + { + Expire(true); + return null; + } + + item.hits++; + item.lastUsed = DateTime.Now; + + Expire(true); + + return item; + } + + // Get an item from cache. Do not try to fetch from source if not + // present. Just return null + // + public virtual Object Get(LLUUID index) + { + CacheItemBase item = GetItem(index); + + if (item == null) + return null; + + return item.Retrieve(); + } + + // Fetch an object from backing store if not cached, serve from + // cache if it is. + // + public virtual Object Get(LLUUID index, FetchDelegate fetch) + { + Object item = Get(index); + if (item != null) + return item; + + Object data = fetch(index); + if (data == null) + { + if ((m_Flags & CacheFlags.CacheMissing) != 0) + { + lock (m_Index) + { + CacheItemBase missing = new CacheItemBase(index); + if (!m_Index.Contains(missing)) + m_Index.Add(missing); + } + } + return null; + } + + Store(index, data); + + return data; + } + + + public virtual void Store(LLUUID index, Object data) + { + Type container; + + switch (m_Medium) + { + case CacheMedium.Memory: + container = typeof(MemoryCacheItem); + break; + case CacheMedium.File: + return; + default: + return; + } + + Store(index, data, container); + } + + public virtual void Store(LLUUID index, Object data, Type container) + { + Store(index, data, container, new Object[] { index }); + } + + public virtual void Store(LLUUID index, Object data, Type container, + Object[] parameters) + { + Expire(false); + + CacheItemBase item; + + lock (m_Index) + { + if (m_Index.Contains(new CacheItemBase(index))) + { + if ((m_Flags & CacheFlags.AllowUpdate) != 0) + { + item = GetItem(index); + + item.hits++; + item.lastUsed = DateTime.Now; + if (m_DefaultTTL.Ticks != 0) + item.expires = DateTime.Now + m_DefaultTTL; + + item.Store(data); + } + return; + } + + item = (CacheItemBase)Activator.CreateInstance(container, + parameters); + + if (m_DefaultTTL.Ticks != 0) + item.expires = DateTime.Now + m_DefaultTTL; + + m_Index.Add(item); + } + item.Store(data); + } + + protected virtual void Expire(bool getting) + { + if (getting && (m_Strategy == CacheStrategy.Aggressive)) + return; + + if (m_DefaultTTL.Ticks != 0) + { + DateTime now= System.DateTime.Now; + + foreach (CacheItemBase item in new List(m_Index)) + { + if (item.expires.Ticks == 0 || + item.expires <= now) + m_Index.Remove(item); + } + } + + switch (m_Strategy) + { + case CacheStrategy.Aggressive: + if (Count < Size) + return; + + lock (m_Index) + { + m_Index.Sort(new SortLRU()); + m_Index.Reverse(); + + int target = (int)((float)Size * 0.9); + if (target == Count) // Cover ridiculous cache sizes + return; + + ExpireDelegate doExpire = OnExpire; + + if (doExpire != null) + { + List candidates = + m_Index.GetRange(target, Count - target); + + foreach (CacheItemBase i in candidates) + { + if (doExpire(i.uuid)) + m_Index.Remove(i); + } + } + else + { + m_Index.RemoveRange(target, Count - target); + } + } + break; + default: + break; + } + } + } } -- cgit v1.1 From 4b6097756f1295e65b4c732606f14f4b43d12fb6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 13 Aug 2008 12:20:49 +0000 Subject: Port the llParcelMediaQuery forward to the new Shared/ directory Add a Dictionary for faster lookup of cached items. --- OpenSim/Framework/Cache.cs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 780e262..7a1d682 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -173,6 +173,8 @@ namespace Opensim.Framework public class Cache { private List m_Index = new List(); + private Dictionary m_Lookup = + new Dictionary(); private CacheStrategy m_Strategy; private CacheMedium m_Medium; @@ -267,6 +269,11 @@ namespace Opensim.Framework m_Index.RemoveRange(newSize, Count - newSize); m_Size = newSize; + + m_Lookup.Clear(); + + foreach (CacheItemBase item in m_Index) + m_Lookup[item.uuid] = item; } } @@ -284,12 +291,8 @@ namespace Opensim.Framework lock (m_Index) { - item = m_Index.Find(delegate(CacheItemBase i) - { - if (i.uuid == index) - return true; - return false; - }); + if(m_Lookup.ContainsKey(index)) + item = m_Lookup[index]; } if (item == null) @@ -337,7 +340,10 @@ namespace Opensim.Framework { CacheItemBase missing = new CacheItemBase(index); if (!m_Index.Contains(missing)) + { m_Index.Add(missing); + m_Lookup[index] = missing; + } } } return null; @@ -404,6 +410,7 @@ namespace Opensim.Framework item.expires = DateTime.Now + m_DefaultTTL; m_Index.Add(item); + m_Lookup[index] = item; } item.Store(data); } @@ -421,7 +428,10 @@ namespace Opensim.Framework { if (item.expires.Ticks == 0 || item.expires <= now) + { m_Index.Remove(item); + m_Lookup.Remove(item.uuid); + } } } @@ -450,12 +460,20 @@ namespace Opensim.Framework foreach (CacheItemBase i in candidates) { if (doExpire(i.uuid)) + { m_Index.Remove(i); + m_Lookup.Remove(i.uuid); + } } } else { m_Index.RemoveRange(target, Count - target); + + m_Lookup.Clear(); + + foreach (CacheItemBase item in m_Index) + m_Lookup[item.uuid] = item; } } break; -- cgit v1.1 From dd1fc5e3fe702d87c189732f4c24df7dbc5cd928 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 13 Aug 2008 14:34:33 +0000 Subject: Add a Find(Predicate) method to the cache to look for items by data other than LLUUID. --- OpenSim/Framework/Cache.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 7a1d682..8d93d3e 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -354,6 +354,17 @@ namespace Opensim.Framework return data; } + // Find an object in cache by delegate. + // + public Object Find(Predicate d) + { + CacheItemBase item = m_Index.Find(d); + + if(item == null) + return null; + + return item.Retrieve(); + } public virtual void Store(LLUUID index, Object data) { -- cgit v1.1 From dde21314e75acdaeff27af70077f283493401961 Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Fri, 15 Aug 2008 10:24:04 +0000 Subject: Update svn properties, formatting cleanup, fix a couple compiler warnings. --- OpenSim/Framework/Cache.cs | 58 +++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 8d93d3e..4746d3c 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -173,8 +173,8 @@ namespace Opensim.Framework public class Cache { private List m_Index = new List(); - private Dictionary m_Lookup = - new Dictionary(); + private Dictionary m_Lookup = + new Dictionary(); private CacheStrategy m_Strategy; private CacheMedium m_Medium; @@ -270,10 +270,10 @@ namespace Opensim.Framework m_Index.RemoveRange(newSize, Count - newSize); m_Size = newSize; - m_Lookup.Clear(); + m_Lookup.Clear(); - foreach (CacheItemBase item in m_Index) - m_Lookup[item.uuid] = item; + foreach (CacheItemBase item in m_Index) + m_Lookup[item.uuid] = item; } } @@ -291,8 +291,8 @@ namespace Opensim.Framework lock (m_Index) { - if(m_Lookup.ContainsKey(index)) - item = m_Lookup[index]; + if (m_Lookup.ContainsKey(index)) + item = m_Lookup[index]; } if (item == null) @@ -340,10 +340,10 @@ namespace Opensim.Framework { CacheItemBase missing = new CacheItemBase(index); if (!m_Index.Contains(missing)) - { + { m_Index.Add(missing); - m_Lookup[index] = missing; - } + m_Lookup[index] = missing; + } } } return null; @@ -354,17 +354,17 @@ namespace Opensim.Framework return data; } - // Find an object in cache by delegate. - // - public Object Find(Predicate d) - { - CacheItemBase item = m_Index.Find(d); + // Find an object in cache by delegate. + // + public Object Find(Predicate d) + { + CacheItemBase item = m_Index.Find(d); - if(item == null) - return null; + if (item == null) + return null; - return item.Retrieve(); - } + return item.Retrieve(); + } public virtual void Store(LLUUID index, Object data) { @@ -421,7 +421,7 @@ namespace Opensim.Framework item.expires = DateTime.Now + m_DefaultTTL; m_Index.Add(item); - m_Lookup[index] = item; + m_Lookup[index] = item; } item.Store(data); } @@ -439,10 +439,10 @@ namespace Opensim.Framework { if (item.expires.Ticks == 0 || item.expires <= now) - { + { m_Index.Remove(item); - m_Lookup.Remove(item.uuid); - } + m_Lookup.Remove(item.uuid); + } } } @@ -471,20 +471,20 @@ namespace Opensim.Framework foreach (CacheItemBase i in candidates) { if (doExpire(i.uuid)) - { + { m_Index.Remove(i); - m_Lookup.Remove(i.uuid); - } + m_Lookup.Remove(i.uuid); + } } } else { m_Index.RemoveRange(target, Count - target); - m_Lookup.Clear(); + m_Lookup.Clear(); - foreach (CacheItemBase item in m_Index) - m_Lookup[item.uuid] = item; + foreach (CacheItemBase item in m_Index) + m_Lookup[item.uuid] = item; } } break; -- cgit v1.1 From 5d6a42a22e7c331551118cea0fc64e3347f83a9c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 17 Aug 2008 19:10:32 +0000 Subject: Add an invalidate method to the cache class. --- OpenSim/Framework/Cache.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 4746d3c..bccda24 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -492,5 +492,15 @@ namespace Opensim.Framework break; } } + + public void Invalidate(LLUUID uuid) + { + if(!m_Lookup.ContainsKey(uuid)) + return; + + CacheItemBase item = m_Lookup[uuid]; + m_Lookup.Remove(uuid); + m_Index.Remove(item); + } } } -- cgit v1.1 From 531f6c01eb8e137016e4e9a20438a107cd7b4f7f Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Sun, 17 Aug 2008 23:07:14 +0000 Subject: Update svn properties, minor formatting cleanup. --- OpenSim/Framework/Cache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index bccda24..d002530 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -495,7 +495,7 @@ namespace Opensim.Framework public void Invalidate(LLUUID uuid) { - if(!m_Lookup.ContainsKey(uuid)) + if (!m_Lookup.ContainsKey(uuid)) return; CacheItemBase item = m_Lookup[uuid]; -- cgit v1.1 From 6ef9d4da901a346c232458317cca6268da888e2e Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Mon, 18 Aug 2008 00:39:10 +0000 Subject: Formatting cleanup. --- OpenSim/Framework/Cache.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index d002530..427072d 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -380,7 +380,7 @@ namespace Opensim.Framework default: return; } - + Store(index, data, container); } @@ -403,7 +403,7 @@ namespace Opensim.Framework if ((m_Flags & CacheFlags.AllowUpdate) != 0) { item = GetItem(index); - + item.hits++; item.lastUsed = DateTime.Now; if (m_DefaultTTL.Ticks != 0) -- cgit v1.1 From 7d89e122930be39e84a6d174548fa2d12ac0484a Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Sat, 6 Sep 2008 07:52:41 +0000 Subject: * This is the fabled LibOMV update with all of the libOMV types from JHurliman * This is a HUGE OMG update and will definitely have unknown side effects.. so this is really only for the strong hearted at this point. Regular people should let the dust settle. * This has been tested to work with most basic functions. However.. make sure you back up 'everything' before using this. It's that big! * Essentially we're back at square 1 in the testing phase.. so lets identify things that broke. --- OpenSim/Framework/Cache.cs | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 427072d..261e0f9 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -1,13 +1,13 @@ using System; using System.Collections.Generic; -using libsecondlife; +using OpenMetaverse; namespace Opensim.Framework { // The delegate we will use for performing fetch from backing store // - public delegate Object FetchDelegate(LLUUID index); - public delegate bool ExpireDelegate(LLUUID index); + public delegate Object FetchDelegate(UUID index); + public delegate bool ExpireDelegate(UUID index); // Strategy // @@ -37,14 +37,14 @@ namespace Opensim.Framework } // The base class of all cache objects. Implements comparison and sorting - // by the LLUUID member. + // by the UUID member. // // This is not abstract because we need to instantiate it briefly as a // method parameter // public class CacheItemBase : IEquatable, IComparable { - public LLUUID uuid; + public UUID uuid; public DateTime entered; public DateTime lastUsed; public DateTime expires = new DateTime(0); @@ -59,14 +59,14 @@ namespace Opensim.Framework { } - public CacheItemBase(LLUUID index) + public CacheItemBase(UUID index) { uuid = index; entered = DateTime.Now; lastUsed = entered; } - public CacheItemBase(LLUUID index, DateTime ttl) + public CacheItemBase(UUID index, DateTime ttl) { uuid = index; entered = DateTime.Now; @@ -96,23 +96,23 @@ namespace Opensim.Framework { private Object m_Data; - public MemoryCacheItem(LLUUID index) : + public MemoryCacheItem(UUID index) : base(index) { } - public MemoryCacheItem(LLUUID index, DateTime ttl) : + public MemoryCacheItem(UUID index, DateTime ttl) : base(index, ttl) { } - public MemoryCacheItem(LLUUID index, Object data) : + public MemoryCacheItem(UUID index, Object data) : base(index) { Store(data); } - public MemoryCacheItem(LLUUID index, DateTime ttl, Object data) : + public MemoryCacheItem(UUID index, DateTime ttl, Object data) : base(index, ttl) { Store(data); @@ -133,23 +133,23 @@ namespace Opensim.Framework // public class FileCacheItem : CacheItemBase { - public FileCacheItem(LLUUID index) : + public FileCacheItem(UUID index) : base(index) { } - public FileCacheItem(LLUUID index, DateTime ttl) : + public FileCacheItem(UUID index, DateTime ttl) : base(index, ttl) { } - public FileCacheItem(LLUUID index, Object data) : + public FileCacheItem(UUID index, Object data) : base(index) { Store(data); } - public FileCacheItem(LLUUID index, DateTime ttl, Object data) : + public FileCacheItem(UUID index, DateTime ttl, Object data) : base(index, ttl) { Store(data); @@ -173,8 +173,8 @@ namespace Opensim.Framework public class Cache { private List m_Index = new List(); - private Dictionary m_Lookup = - new Dictionary(); + private Dictionary m_Lookup = + new Dictionary(); private CacheStrategy m_Strategy; private CacheMedium m_Medium; @@ -285,7 +285,7 @@ namespace Opensim.Framework // Get an item from cache. Return the raw item, not it's data // - protected virtual CacheItemBase GetItem(LLUUID index) + protected virtual CacheItemBase GetItem(UUID index) { CacheItemBase item = null; @@ -312,7 +312,7 @@ namespace Opensim.Framework // Get an item from cache. Do not try to fetch from source if not // present. Just return null // - public virtual Object Get(LLUUID index) + public virtual Object Get(UUID index) { CacheItemBase item = GetItem(index); @@ -325,7 +325,7 @@ namespace Opensim.Framework // Fetch an object from backing store if not cached, serve from // cache if it is. // - public virtual Object Get(LLUUID index, FetchDelegate fetch) + public virtual Object Get(UUID index, FetchDelegate fetch) { Object item = Get(index); if (item != null) @@ -366,7 +366,7 @@ namespace Opensim.Framework return item.Retrieve(); } - public virtual void Store(LLUUID index, Object data) + public virtual void Store(UUID index, Object data) { Type container; @@ -384,12 +384,12 @@ namespace Opensim.Framework Store(index, data, container); } - public virtual void Store(LLUUID index, Object data, Type container) + public virtual void Store(UUID index, Object data, Type container) { Store(index, data, container, new Object[] { index }); } - public virtual void Store(LLUUID index, Object data, Type container, + public virtual void Store(UUID index, Object data, Type container, Object[] parameters) { Expire(false); @@ -493,7 +493,7 @@ namespace Opensim.Framework } } - public void Invalidate(LLUUID uuid) + public void Invalidate(UUID uuid) { if (!m_Lookup.ContainsKey(uuid)) return; -- cgit v1.1 From ee9033e2c72474c953dbc60a1a43a97f3471868e Mon Sep 17 00:00:00 2001 From: Charles Krinke Date: Sun, 28 Sep 2008 17:11:10 +0000 Subject: Mantis#2288. Thank you kindly, SMeans, for a patch that: Corrects the typo of namespace Opensim.Framework to OpenSim.Framework in Cache.cs. --- OpenSim/Framework/Cache.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 261e0f9..95adb2c 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using OpenMetaverse; -namespace Opensim.Framework +namespace OpenSim.Framework { // The delegate we will use for performing fetch from backing store // @@ -356,7 +356,7 @@ namespace Opensim.Framework // Find an object in cache by delegate. // - public Object Find(Predicate d) + public Object Find(Predicate d) { CacheItemBase item = m_Index.Find(d); -- cgit v1.1 From bbb8d6fc51020a8734163313bfc0b8aac9e402c2 Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Sat, 8 Nov 2008 14:28:43 +0000 Subject: Remove empty OSUUID.cs file. Add copyright headers. Minor formatting cleanup. --- OpenSim/Framework/Cache.cs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 95adb2c..6c37c66 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -1,3 +1,30 @@ +/* + * 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 OpenMetaverse; -- cgit v1.1 From 801da4346aeb3c08969c4845f5c595135a64470a Mon Sep 17 00:00:00 2001 From: lbsa71 Date: Thu, 12 Feb 2009 09:53:12 +0000 Subject: * optimized usings. --- OpenSim/Framework/Cache.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 6c37c66..3dab9b6 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -383,7 +383,7 @@ namespace OpenSim.Framework // Find an object in cache by delegate. // - public Object Find(Predicate d) + public Object Find(Predicate d) { CacheItemBase item = m_Index.Find(d); @@ -460,7 +460,7 @@ namespace OpenSim.Framework if (m_DefaultTTL.Ticks != 0) { - DateTime now= System.DateTime.Now; + DateTime now= DateTime.Now; foreach (CacheItemBase item in new List(m_Index)) { -- cgit v1.1 From d8e1842d2507b2c18b21671ed01496b3a2c59e18 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 10 May 2009 12:27:05 +0000 Subject: Add some asset cache plumbing. Change the generic cache from UUID to string keys to allow caching the new crop of URI identified objects. --- OpenSim/Framework/Cache.cs | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 3dab9b6..2d49146 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -33,8 +33,8 @@ namespace OpenSim.Framework { // The delegate we will use for performing fetch from backing store // - public delegate Object FetchDelegate(UUID index); - public delegate bool ExpireDelegate(UUID index); + public delegate Object FetchDelegate(string index); + public delegate bool ExpireDelegate(string index); // Strategy // @@ -64,14 +64,14 @@ namespace OpenSim.Framework } // The base class of all cache objects. Implements comparison and sorting - // by the UUID member. + // by the string member. // // This is not abstract because we need to instantiate it briefly as a // method parameter // public class CacheItemBase : IEquatable, IComparable { - public UUID uuid; + public string uuid; public DateTime entered; public DateTime lastUsed; public DateTime expires = new DateTime(0); @@ -86,14 +86,14 @@ namespace OpenSim.Framework { } - public CacheItemBase(UUID index) + public CacheItemBase(string index) { uuid = index; entered = DateTime.Now; lastUsed = entered; } - public CacheItemBase(UUID index, DateTime ttl) + public CacheItemBase(string index, DateTime ttl) { uuid = index; entered = DateTime.Now; @@ -123,23 +123,23 @@ namespace OpenSim.Framework { private Object m_Data; - public MemoryCacheItem(UUID index) : + public MemoryCacheItem(string index) : base(index) { } - public MemoryCacheItem(UUID index, DateTime ttl) : + public MemoryCacheItem(string index, DateTime ttl) : base(index, ttl) { } - public MemoryCacheItem(UUID index, Object data) : + public MemoryCacheItem(string index, Object data) : base(index) { Store(data); } - public MemoryCacheItem(UUID index, DateTime ttl, Object data) : + public MemoryCacheItem(string index, DateTime ttl, Object data) : base(index, ttl) { Store(data); @@ -160,23 +160,23 @@ namespace OpenSim.Framework // public class FileCacheItem : CacheItemBase { - public FileCacheItem(UUID index) : + public FileCacheItem(string index) : base(index) { } - public FileCacheItem(UUID index, DateTime ttl) : + public FileCacheItem(string index, DateTime ttl) : base(index, ttl) { } - public FileCacheItem(UUID index, Object data) : + public FileCacheItem(string index, Object data) : base(index) { Store(data); } - public FileCacheItem(UUID index, DateTime ttl, Object data) : + public FileCacheItem(string index, DateTime ttl, Object data) : base(index, ttl) { Store(data); @@ -200,8 +200,8 @@ namespace OpenSim.Framework public class Cache { private List m_Index = new List(); - private Dictionary m_Lookup = - new Dictionary(); + private Dictionary m_Lookup = + new Dictionary(); private CacheStrategy m_Strategy; private CacheMedium m_Medium; @@ -312,7 +312,7 @@ namespace OpenSim.Framework // Get an item from cache. Return the raw item, not it's data // - protected virtual CacheItemBase GetItem(UUID index) + protected virtual CacheItemBase GetItem(string index) { CacheItemBase item = null; @@ -339,7 +339,7 @@ namespace OpenSim.Framework // Get an item from cache. Do not try to fetch from source if not // present. Just return null // - public virtual Object Get(UUID index) + public virtual Object Get(string index) { CacheItemBase item = GetItem(index); @@ -352,7 +352,7 @@ namespace OpenSim.Framework // Fetch an object from backing store if not cached, serve from // cache if it is. // - public virtual Object Get(UUID index, FetchDelegate fetch) + public virtual Object Get(string index, FetchDelegate fetch) { Object item = Get(index); if (item != null) @@ -393,7 +393,7 @@ namespace OpenSim.Framework return item.Retrieve(); } - public virtual void Store(UUID index, Object data) + public virtual void Store(string index, Object data) { Type container; @@ -411,12 +411,12 @@ namespace OpenSim.Framework Store(index, data, container); } - public virtual void Store(UUID index, Object data, Type container) + public virtual void Store(string index, Object data, Type container) { Store(index, data, container, new Object[] { index }); } - public virtual void Store(UUID index, Object data, Type container, + public virtual void Store(string index, Object data, Type container, Object[] parameters) { Expire(false); @@ -520,7 +520,7 @@ namespace OpenSim.Framework } } - public void Invalidate(UUID uuid) + public void Invalidate(string uuid) { if (!m_Lookup.ContainsKey(uuid)) return; -- cgit v1.1 From 1a910b6e1dbace70b27581c51148a8732b46de79 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 10 May 2009 14:03:06 +0000 Subject: Connect up the new asset cache and introduce an asynchronous call path for asset retrieval (full asset only) to ease migration to the new system --- OpenSim/Framework/Cache.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'OpenSim/Framework/Cache.cs') diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 2d49146..79e20fc 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -529,5 +529,11 @@ namespace OpenSim.Framework m_Lookup.Remove(uuid); m_Index.Remove(item); } + + public void Clear() + { + m_Index.Clear(); + m_Lookup.Clear(); + } } } -- cgit v1.1 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(-) (limited to 'OpenSim/Framework/Cache.cs') 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